Path: blob/master/src/sage/schemes/toric/fano_variety.py
8820 views
r"""1Fano toric varieties23This module provides support for (Crepant Partial Resolutions of) Fano toric4varieties, corresponding to crepant subdivisions of face fans of reflexive5:class:`lattice polytopes6<sage.geometry.lattice_polytope.LatticePolytopeClass>`.7The interface is provided via :func:`CPRFanoToricVariety`.89A careful exposition of different flavours of Fano varieties can be found in10the paper by Benjamin Nill [Nill2005]_. The main goal of this module is to11support work with **Gorenstein weak Fano toric varieties**. Such a variety12corresponds to a **coherent crepant refinement of the normal fan of a13reflexive polytope** `\Delta`, where crepant means that primitive generators14of the refining rays lie on the facets of the polar polytope `\Delta^\circ`15and coherent (a.k.a. regular or projective) means that there exists a strictly16upper convex piecewise linear function whose domains of linearity are17precisely the maximal cones of the subdivision. These varieties are important18for string theory in physics, as they serve as ambient spaces for mirror pairs19of Calabi-Yau manifolds via constructions due to Victor V. Batyrev20[Batyrev1994]_ and Lev A. Borisov [Borisov1993]_.2122From the combinatorial point of view "crepant" requirement is much more simple23and natural to work with than "coherent." For this reason, the code in this24module will allow work with arbitrary crepant subdivisions without checking25whether they are coherent or not. We refer to corresponding toric varieties as26**CPR-Fano toric varieties**.2728REFERENCES:2930.. [Batyrev1994]31Victor V. Batyrev,32"Dual polyhedra and mirror symmetry for Calabi-Yau hypersurfaces in toric33varieties",34J. Algebraic Geom. 3 (1994), no. 3, 493-535.35arXiv:alg-geom/9310003v13637.. [Borisov1993]38Lev A. Borisov,39"Towards the mirror symmetry for Calabi-Yau complete intersections in40Gorenstein Fano toric varieties", 1993.41arXiv:alg-geom/9310001v14243.. [CD2007]44Adrian Clingher and Charles F. Doran,45"Modular invariants for lattice polarized K3 surfaces",46Michigan Math. J. 55 (2007), no. 2, 355-393.47arXiv:math/0602146v1 [math.AG]4849.. [Nill2005]50Benjamin Nill,51"Gorenstein toric Fano varieties",52Manuscripta Math. 116 (2005), no. 2, 183-210.53arXiv:math/0405448v1 [math.AG]5455AUTHORS:5657- Andrey Novoseltsev (2010-05-18): initial version.5859EXAMPLES:6061Most of the functions available for Fano toric varieties are the same as62for general toric varieties, so here we will concentrate only on63Calabi-Yau subvarieties, which were the primary goal for creating this64module.6566For our first example we realize the projective plane as a Fano toric67variety::6869sage: simplex = lattice_polytope.projective_space(2)70sage: P2 = CPRFanoToricVariety(Delta_polar=simplex)7172Its anticanonical "hypersurface" is a one-dimensional Calabi-Yau73manifold::7475sage: P2.anticanonical_hypersurface(76... monomial_points="all")77Closed subscheme of 2-d CPR-Fano toric variety78covered by 3 affine patches defined by:79a0*z0^3 + a9*z0^2*z1 + a7*z0*z1^280+ a1*z1^3 + a8*z0^2*z2 + a6*z0*z1*z281+ a4*z1^2*z2 + a5*z0*z2^282+ a3*z1*z2^2 + a2*z2^38384In many cases it is sufficient to work with the "simplified polynomial85moduli space" of anticanonical hypersurfaces::8687sage: P2.anticanonical_hypersurface(88... monomial_points="simplified")89Closed subscheme of 2-d CPR-Fano toric variety90covered by 3 affine patches defined by:91a0*z0^3 + a1*z1^3 + a6*z0*z1*z2 + a2*z2^39293The mirror family to these hypersurfaces lives inside the Fano toric94variety obtained using ``simplex`` as ``Delta`` instead of ``Delta_polar``::9596sage: FTV = CPRFanoToricVariety(Delta=simplex,97... coordinate_points="all")98sage: FTV.anticanonical_hypersurface(99... monomial_points="simplified")100Closed subscheme of 2-d CPR-Fano toric variety101covered by 9 affine patches defined by:102a2*z2^3*z3^2*z4*z5^2*z8103+ a1*z1^3*z3*z4^2*z7^2*z9104+ a3*z0*z1*z2*z3*z4*z5*z7*z8*z9105+ a0*z0^3*z5*z7*z8^2*z9^2106107Here we have taken the resolved version of the ambient space for the108mirror family, but in fact we don't have to resolve singularities109corresponding to the interior points of facets - they are singular110points which do not lie on a generic anticanonical hypersurface::111112sage: FTV = CPRFanoToricVariety(Delta=simplex,113... coordinate_points="all but facets")114sage: FTV.anticanonical_hypersurface(115... monomial_points="simplified")116Closed subscheme of 2-d CPR-Fano toric variety117covered by 3 affine patches defined by:118a0*z0^3 + a1*z1^3 + a3*z0*z1*z2 + a2*z2^3119120This looks very similar to our second version of the anticanonical121hypersurface of the projective plane, as expected, since all122one-dimensional Calabi-Yau manifolds are elliptic curves!123124Now let's take a look at a toric realization of `M`-polarized K3 surfaces125studied by Adrian Clingher and Charles F. Doran in [CD2007]_::126127sage: p4318 = ReflexivePolytope(3, 4318) # long time128sage: FTV = CPRFanoToricVariety(Delta_polar=p4318) # long time129sage: FTV.anticanonical_hypersurface() # long time130Closed subscheme of 3-d CPR-Fano toric variety131covered by 4 affine patches defined by:132a3*z2^12 + a4*z2^6*z3^6 + a2*z3^12133+ a8*z0*z1*z2*z3 + a0*z1^3 + a1*z0^2134135Below you will find detailed descriptions of available functions. Current136functionality of this module is very basic, but it is under active137development and hopefully will improve in future releases of Sage. If there138are some particular features that you would like to see implemented ASAP,139please consider reporting them to the Sage Development Team or even140implementing them on your own as a patch for inclusion!141"""142# The first example of the tutorial is taken from143# CPRFanoToricVariety_field.anticanonical_hypersurface144145146#*****************************************************************************147# Copyright (C) 2010 Andrey Novoseltsev <[email protected]>148# Copyright (C) 2010 William Stein <[email protected]>149#150# Distributed under the terms of the GNU General Public License (GPL)151#152# http://www.gnu.org/licenses/153#*****************************************************************************154155import re156157from sage.geometry.all import Cone, FaceFan, Fan, LatticePolytope158from sage.misc.all import latex, prod159from sage.rings.all import (PolynomialRing, QQ)160161from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing162from sage.rings.polynomial.polynomial_ring import is_PolynomialRing163from sage.rings.fraction_field import is_FractionField164165from sage.schemes.generic.algebraic_scheme import AlgebraicScheme_subscheme_toric166from sage.schemes.toric.variety import (167ToricVariety_field,168normalize_names)169from sage.structure.all import get_coercion_model170from sage.categories.fields import Fields171_Fields = Fields()172173174# Default coefficient for anticanonical hypersurfaces175DEFAULT_COEFFICIENT = "a"176# Default coefficients for nef complete intersections177DEFAULT_COEFFICIENTS = tuple(chr(i) for i in range(ord("a"), ord("z") + 1))178179180def is_CPRFanoToricVariety(x):181r"""182Check if ``x`` is a CPR-Fano toric variety.183184INPUT:185186- ``x`` -- anything.187188OUTPUT:189190- ``True`` if ``x`` is a :class:`CPR-Fano toric variety191<CPRFanoToricVariety_field>` and ``False`` otherwise.192193.. NOTE::194195While projective spaces are Fano toric varieties mathematically, they196are not toric varieties in Sage due to efficiency considerations, so197this function will return ``False``.198199EXAMPLES::200201sage: from sage.schemes.toric.fano_variety import (202... is_CPRFanoToricVariety)203sage: is_CPRFanoToricVariety(1)204False205sage: FTV = CPRFanoToricVariety(lattice_polytope.octahedron(2))206sage: FTV2072-d CPR-Fano toric variety covered by 4 affine patches208sage: is_CPRFanoToricVariety(FTV)209True210sage: is_CPRFanoToricVariety(ProjectiveSpace(2))211False212"""213return isinstance(x, CPRFanoToricVariety_field)214215216def CPRFanoToricVariety(Delta=None,217Delta_polar=None,218coordinate_points=None,219charts=None,220coordinate_names=None,221names=None,222coordinate_name_indices=None,223make_simplicial=False,224base_ring=None,225base_field=None,226check=True):227r"""228Construct a CPR-Fano toric variety.229230.. NOTE::231232See documentation of the module233:mod:`~sage.schemes.toric.fano_variety` for the used234definitions and supported varieties.235236Due to the large number of available options, it is recommended to always237use keyword parameters.238239INPUT:240241- ``Delta`` -- reflexive :class:`lattice polytope242<sage.geometry.lattice_polytope.LatticePolytopeClass>`. The fan of the243constructed CPR-Fano toric variety will be a crepant subdivision of the244*normal fan* of ``Delta``. Either ``Delta`` or ``Delta_polar`` must be245given, but not both at the same time, since one is completely determined246by another via :meth:`polar247<sage.geometry.lattice_polytope.LatticePolytopeClass.polar>` method;248249- ``Delta_polar`` -- reflexive :class:`lattice polytope250<sage.geometry.lattice_polytope.LatticePolytopeClass>`. The fan of the251constructed CPR-Fano toric variety will be a crepant subdivision of the252*face fan* of ``Delta_polar``. Either ``Delta`` or ``Delta_polar`` must253be given, but not both at the same time, since one is completely254determined by another via :meth:`polar255<sage.geometry.lattice_polytope.LatticePolytopeClass.polar>` method;256257- ``coordinate_points`` -- list of integers or string. A list will be258interpreted as indices of (boundary) points of ``Delta_polar`` which259should be used as rays of the underlying fan. It must include all260vertices of ``Delta_polar`` and no repetitions are allowed. A string261must be one of the following descriptions of points of ``Delta_polar``:262263* "vertices" (default),264* "all" (will not include the origin),265* "all but facets" (will not include points in the relative interior of266facets);267268- ``charts`` -- list of lists of elements from ``coordinate_points``. Each269of these lists must define a generating cone of a fan subdividing the270normal fan of ``Delta``. Default ``charts`` correspond to the normal fan271of ``Delta`` without subdivision. The fan specified by ``charts`` will272be subdivided to include all of the requested ``coordinate_points``;273274- ``coordinate_names`` -- names of variables for the coordinate ring, see275:func:`~sage.schemes.toric.variety.normalize_names`276for acceptable formats. If not given, indexed variable names will be277created automatically;278279- ``names`` -- an alias of ``coordinate_names`` for internal280use. You may specify either ``names`` or ``coordinate_names``,281but not both;282283- ``coordinate_name_indices`` -- list of integers, indices for indexed284variables. If not given, the index of each variable will coincide with285the index of the corresponding point of ``Delta_polar``;286287- ``make_simplicial`` -- if ``True``, the underlying fan will be made288simplicial (default: ``False``);289290- ``base_ring`` -- base field of the CPR-Fano toric variety291(default: `\QQ`);292293- ``base_field`` -- alias for ``base_ring``. Takes precedence if294both are specified.295296- ``check`` -- by default the input data will be checked for correctness297(e.g. that ``charts`` do form a subdivision of the normal fan of298``Delta``). If you know for sure that the input is valid, you may299significantly decrease construction time using ``check=False`` option.300301OUTPUT:302303- :class:`CPR-Fano toric variety <CPRFanoToricVariety_field>`.304305EXAMPLES:306307We start with the product of two projective lines::308309sage: diamond = lattice_polytope.octahedron(2)310sage: diamond.vertices()311[ 1 0 -1 0]312[ 0 1 0 -1]313sage: P1xP1 = CPRFanoToricVariety(Delta_polar=diamond)314sage: P1xP13152-d CPR-Fano toric variety covered by 4 affine patches316sage: P1xP1.fan()317Rational polyhedral fan in 2-d lattice N318sage: P1xP1.fan().rays()319N( 1, 0),320N( 0, 1),321N(-1, 0),322N( 0, -1)323in 2-d lattice N324325"Unfortunately," this variety is smooth to start with and we cannot326perform any subdivisions of the underlying fan without leaving the327category of CPR-Fano toric varieties. Our next example starts with a328square::329330sage: square = diamond.polar()331sage: square.vertices()332[-1 1 -1 1]333[ 1 1 -1 -1]334sage: square.points()335[-1 1 -1 1 -1 0 0 0 1]336[ 1 1 -1 -1 0 -1 0 1 0]337338We will construct several varieties associated to it::339340sage: FTV = CPRFanoToricVariety(Delta_polar=square)341sage: FTV.fan().rays()342N(-1, 1),343N( 1, 1),344N(-1, -1),345N( 1, -1)346in 2-d lattice N347sage: FTV.gens()348(z0, z1, z2, z3)349350sage: FTV = CPRFanoToricVariety(Delta_polar=square,351... coordinate_points=[0,1,2,3,8])352sage: FTV.fan().rays()353N(-1, 1),354N( 1, 1),355N(-1, -1),356N( 1, -1),357N( 1, 0)358in 2-d lattice N359sage: FTV.gens()360(z0, z1, z2, z3, z8)361362sage: FTV = CPRFanoToricVariety(Delta_polar=square,363... coordinate_points=[8,0,2,1,3],364... coordinate_names="x+")365sage: FTV.fan().rays()366N( 1, 0),367N(-1, 1),368N(-1, -1),369N( 1, 1),370N( 1, -1)371in 2-d lattice N372sage: FTV.gens()373(x8, x0, x2, x1, x3)374375sage: FTV = CPRFanoToricVariety(Delta_polar=square,376... coordinate_points="all",377... coordinate_names="x y Z+")378sage: FTV.fan().rays()379N(-1, 1),380N( 1, 1),381N(-1, -1),382N( 1, -1),383N(-1, 0),384N( 0, -1),385N( 0, 1),386N( 1, 0)387in 2-d lattice N388sage: FTV.gens()389(x, y, Z2, Z3, Z4, Z5, Z7, Z8)390391Note that ``Z6`` is "missing". This is due to the fact that the 6-th point392of ``square`` is the origin, and all automatically created names have the393same indices as corresponding points of394:meth:`~CPRFanoToricVariety_field.Delta_polar`. This is usually very395convenient, especially if you have to work with several partial396resolutions of the same Fano toric variety. However, you can change it, if397you want::398399sage: FTV = CPRFanoToricVariety(Delta_polar=square,400... coordinate_points="all",401... coordinate_names="x y Z+",402... coordinate_name_indices=range(8))403sage: FTV.gens()404(x, y, Z2, Z3, Z4, Z5, Z6, Z7)405406Note that you have to provide indices for *all* variables, including those407that have "completely custom" names. Again, this is usually convenient,408because you can add or remove "custom" variables without disturbing too409much "automatic" ones::410411sage: FTV = CPRFanoToricVariety(Delta_polar=square,412... coordinate_points="all",413... coordinate_names="x Z+",414... coordinate_name_indices=range(8))415sage: FTV.gens()416(x, Z1, Z2, Z3, Z4, Z5, Z6, Z7)417418If you prefer to always start from zero, you will have to shift indices419accordingly::420421sage: FTV = CPRFanoToricVariety(Delta_polar=square,422... coordinate_points="all",423... coordinate_names="x Z+",424... coordinate_name_indices=[0] + range(7))425sage: FTV.gens()426(x, Z0, Z1, Z2, Z3, Z4, Z5, Z6)427428sage: FTV = CPRFanoToricVariety(Delta_polar=square,429... coordinate_points="all",430... coordinate_names="x y Z+",431... coordinate_name_indices=[0]*2 + range(6))432sage: FTV.gens()433(x, y, Z0, Z1, Z2, Z3, Z4, Z5)434435So you always can get any names you want, somewhat complicated default436behaviour was designed with the hope that in most cases you will have no437desire to provide different names.438439Now we will use the possibility to specify initial charts::440441sage: charts = [(0,1), (1,3), (3,2), (2,0)]442443(these charts actually form exactly the face fan of our square) ::444445sage: FTV = CPRFanoToricVariety(Delta_polar=square,446... coordinate_points=[0,1,2,3,4],447... charts=charts)448sage: FTV.fan().rays()449N(-1, 1),450N( 1, 1),451N(-1, -1),452N( 1, -1),453N(-1, 0)454in 2-d lattice N455sage: [cone.ambient_ray_indices() for cone in FTV.fan()]456[(0, 1), (1, 3), (2, 3), (2, 4), (0, 4)]457458If charts are wrong, it should be detected::459460sage: bad_charts = charts + [(2,0)]461sage: FTV = CPRFanoToricVariety(Delta_polar=square,462... coordinate_points=[0,1,2,3,4],463... charts=bad_charts)464Traceback (most recent call last):465...466ValueError: you have provided 5 cones, but only 4 of them are maximal!467Use discard_faces=True if you indeed need to construct a fan from468these cones.469470These charts are technically correct, they just happened to list one of471them twice, but it is assumed that such a situation will not happen. It is472especially important when you try to speed up your code::473474sage: FTV = CPRFanoToricVariety(Delta_polar=square,475... coordinate_points=[0,1,2,3,4],476... charts=bad_charts,477... check=False)478sage: FTV.fan().rays()479N(-1, 1),480N( 1, 1),481N(-1, -1),482N( 1, -1),483N(-1, 0)484in 2-d lattice N485sage: [cone.ambient_ray_indices() for cone in FTV.fan()]486[(0, 1), (1, 3), (2, 3), (2, 4), (0, 4), (2, 4), (0, 4)]487488The last line shows two of the generating cones twice. While "everything489still works" in the sense "it does not crash," any work with such a490variety may lead to mathematically wrong results, so use ``check=False``491carefully!492493Here are some other possible mistakes::494495sage: bad_charts = charts + [(0,3)]496sage: FTV = CPRFanoToricVariety(Delta_polar=square,497... coordinate_points=[0,1,2,3,4],498... charts=bad_charts)499Traceback (most recent call last):500...501ValueError: (0, 3) does not form a chart of a502subdivision of the face fan of A polytope polar503to An octahedron: 2-dimensional, 4 vertices.!504505sage: bad_charts = charts[:-1]506sage: FTV = CPRFanoToricVariety(Delta_polar=square,507... coordinate_points=[0,1,2,3,4],508... charts=bad_charts)509Traceback (most recent call last):510...511ValueError: given charts do not form a complete fan!512513sage: FTV = CPRFanoToricVariety(Delta_polar=square,514... coordinate_points=[1,2,3,4])515Traceback (most recent call last):516...517ValueError: all 4 vertices of Delta_polar518must be used for coordinates!519Got: [1, 2, 3, 4]520521sage: FTV = CPRFanoToricVariety(Delta_polar=square,522... coordinate_points=[0,0,1,2,3,4])523Traceback (most recent call last):524...525ValueError: no repetitions are526allowed for coordinate points!527Got: [0, 0, 1, 2, 3, 4]528529sage: FTV = CPRFanoToricVariety(Delta_polar=square,530... coordinate_points=[0,1,2,3,6])531Traceback (most recent call last):532...533ValueError: the origin (point #6)534cannot be used for a coordinate!535Got: [0, 1, 2, 3, 6]536537Here is a shorthand for defining the toric variety and homogeneous538coordinates in one go::539540sage: P1xP1.<a,b,c,d> = CPRFanoToricVariety(Delta_polar=diamond)541sage: (a^2+b^2) * (c+d)542a^2*c + b^2*c + a^2*d + b^2*d543"""544if names is not None:545if coordinate_names is not None:546raise ValueError('You must not specify both coordinate_names and names!')547coordinate_names = names548# Check/normalize Delta_polar549if Delta is None and Delta_polar is None:550raise ValueError("either Delta or Delta_polar must be given!")551elif Delta is not None and Delta_polar is not None:552raise ValueError("Delta and Delta_polar cannot be given together!")553elif Delta_polar is None:554Delta_polar = Delta.polar()555elif not Delta_polar.is_reflexive():556raise ValueError("Delta_polar must be reflexive!")557# Check/normalize coordinate_points and construct fan rays558if coordinate_points is None:559coordinate_points = range(Delta_polar.nvertices())560if charts is not None:561for chart in charts:562for point in chart:563if point not in coordinate_points:564coordinate_points.append(point)565elif coordinate_points == "vertices":566coordinate_points = range(Delta_polar.nvertices())567elif coordinate_points == "all":568coordinate_points = range(Delta_polar.npoints())569coordinate_points.remove(Delta_polar.origin())570elif coordinate_points == "all but facets":571coordinate_points = Delta_polar.skeleton_points(Delta_polar.dim() - 2)572elif isinstance(coordinate_points, str):573raise ValueError("unrecognized description of the coordinate points!"574"\nGot: %s" % coordinate_points)575elif check:576cp_set = set(coordinate_points)577if len(cp_set) != len(coordinate_points):578raise ValueError(579"no repetitions are allowed for coordinate points!\nGot: %s"580% coordinate_points)581if not cp_set.issuperset(range(Delta_polar.nvertices())):582raise ValueError("all %d vertices of Delta_polar must be used "583"for coordinates!\nGot: %s"584% (Delta_polar.nvertices(), coordinate_points))585if Delta_polar.origin() in cp_set:586raise ValueError("the origin (point #%d) cannot be used for a "587"coordinate!\nGot: %s"588% (Delta_polar.origin(), coordinate_points))589point_to_ray = dict()590for n, point in enumerate(coordinate_points):591point_to_ray[point] = n592# This can be simplified if LatticePolytopeClass is adjusted.593rays = [Delta_polar.point(p) for p in coordinate_points]594for ray in rays:595ray.set_immutable()596# Check/normalize charts and construct the fan based on them.597if charts is None:598# Start with the face fan599fan = FaceFan(Delta_polar)600else:601# First of all, check that each chart is completely contained in a602# single facet of Delta_polar, otherwise they do not form a603# subdivision of the face fan of Delta_polar604if check:605facet_sets = [frozenset(facet.points())606for facet in Delta_polar.facets()]607for chart in charts:608is_bad = True609for fset in facet_sets:610if fset.issuperset(chart):611is_bad = False612break613if is_bad:614raise ValueError(615"%s does not form a chart of a subdivision of the "616"face fan of %s!" % (chart, Delta_polar))617# We will construct the initial fan from Cone objects: since charts618# may not use all of the necessary rays, alternative form is tedious619# With check=False it should not be long anyway.620cones = [Cone((rays[point_to_ray[point]] for point in chart),621check=check)622for chart in charts]623fan = Fan(cones, check=check)624if check and not fan.is_complete():625raise ValueError("given charts do not form a complete fan!")626# Subdivide this fan to use all required points627fan = fan.subdivide(new_rays=(ray for ray in rays628if ray not in fan.rays().set()),629make_simplicial=make_simplicial)630# Now create yet another fan making sure that the order of the rays is631# the same as requested (it is a bit difficult to get it from the start)632trans = dict()633for n, ray in enumerate(fan.rays()):634trans[n] = rays.index(ray)635cones = tuple(tuple(sorted(trans[r] for r in cone.ambient_ray_indices()))636for cone in fan)637fan = Fan(cones, rays, check=False)638# Check/normalize base_field639if base_field is not None:640base_ring = base_field641if base_ring is None:642base_ring = QQ643elif base_ring not in _Fields:644raise TypeError("need a field to construct a Fano toric variety!"645"\n Got %s" % base_ring)646fan._is_complete = True # At this point it must be for sure647return CPRFanoToricVariety_field(648Delta_polar, fan, coordinate_points,649point_to_ray, coordinate_names, coordinate_name_indices, base_ring)650651652class CPRFanoToricVariety_field(ToricVariety_field):653r"""654Construct a CPR-Fano toric variety associated to a reflexive polytope.655656.. WARNING::657658This class does not perform any checks of correctness of input and it659does assume that the internal structure of the given parameters is660coordinated in a certain way. Use661:func:`CPRFanoToricVariety` to construct CPR-Fano toric varieties.662663.. NOTE::664665See documentation of the module666:mod:`~sage.schemes.toric.fano_variety` for the used667definitions and supported varieties.668669INPUT:670671- ``Delta_polar`` -- reflexive polytope;672673- ``fan`` -- rational polyhedral fan subdividing the face fan of674``Delta_polar``;675676- ``coordinate_points`` -- list of indices of points of ``Delta_polar``677used for rays of ``fan``;678679- ``point_to_ray`` -- dictionary mapping the index of a coordinate point680to the index of the corresponding ray;681682- ``coordinate_names`` -- names of the variables of the coordinate ring in683the format accepted by684:func:`~sage.schemes.toric.variety.normalize_names`;685686- ``coordinate_name_indices`` -- indices for indexed variables,687if ``None``, will be equal to ``coordinate_points``;688689- ``base_field`` -- base field of the CPR-Fano toric variety.690691OUTPUT:692693- :class:`CPR-Fano toric variety <CPRFanoToricVariety_field>`.694695TESTS::696697sage: P1xP1 = CPRFanoToricVariety(698... Delta_polar=lattice_polytope.octahedron(2))699sage: P1xP17002-d CPR-Fano toric variety covered by 4 affine patches701"""702703def __init__(self, Delta_polar, fan, coordinate_points, point_to_ray,704coordinate_names, coordinate_name_indices, base_field):705r"""706See :class:`CPRFanoToricVariety_field` for documentation.707708Use ``CPRFanoToricVariety`` to construct CPR-Fano toric varieties.709710TESTS::711712sage: P1xP1 = CPRFanoToricVariety(713... Delta_polar=lattice_polytope.octahedron(2))714sage: P1xP17152-d CPR-Fano toric variety covered by 4 affine patches716"""717self._Delta_polar = Delta_polar718self._coordinate_points = tuple(coordinate_points)719self._point_to_ray = point_to_ray720# Check/normalize coordinate_indices721if coordinate_name_indices is None:722coordinate_name_indices = coordinate_points723super(CPRFanoToricVariety_field, self).__init__(fan, coordinate_names,724coordinate_name_indices, base_field)725726def _latex_(self):727r"""728Return a LaTeX representation of ``self``.729730OUTPUT:731732- string.733734TESTS::735736sage: P1xP1 = CPRFanoToricVariety(737... Delta_polar=lattice_polytope.octahedron(2))738sage: P1xP1._latex_()739'\\mathbb{P}_{\\Delta^{2}}'740"""741return r"\mathbb{P}_{%s}" % latex(self.Delta())742743def _repr_(self):744r"""745Return a string representation of ``self``.746747OUTPUT:748749- string.750751TESTS::752753sage: P1xP1 = CPRFanoToricVariety(754... Delta_polar=lattice_polytope.octahedron(2))755sage: P1xP1._repr_()756'2-d CPR-Fano toric variety covered by 4 affine patches'757"""758return ("%d-d CPR-Fano toric variety covered by %d affine patches"759% (self.dimension_relative(), self.fan().ngenerating_cones()))760761def anticanonical_hypersurface(self, **kwds):762r"""763Return an anticanonical hypersurface of ``self``.764765.. NOTE::766767The returned hypersurface may be actually a subscheme of768**another** CPR-Fano toric variety: if the base field of ``self``769does not include all of the required names for generic monomial770coefficients, it will be automatically extended.771772Below `\Delta` is the reflexive polytope corresponding to ``self``,773i.e. the fan of ``self`` is a refinement of the normal fan of774`\Delta`. This function accepts only keyword parameters.775776INPUT:777778- ``monomial points`` -- a list of integers or a string. A list will be779interpreted as indices of points of `\Delta` which should be used780for monomials of this hypersurface. A string must be one of the781following descriptions of points of `\Delta`:782783* "vertices",784* "vertices+origin",785* "all",786* "simplified" (default) -- all points of `\Delta` except for787the interior points of facets, this choice corresponds to working788with the "simplified polynomial moduli space" of anticanonical789hypersurfaces;790791- ``coefficient_names`` -- names for the monomial coefficients, see792:func:`~sage.schemes.toric.variety.normalize_names`793for acceptable formats. If not given, indexed coefficient names will794be created automatically;795796- ``coefficient_name_indices`` -- a list of integers, indices for797indexed coefficients. If not given, the index of each coefficient798will coincide with the index of the corresponding point of `\Delta`;799800- ``coefficients`` -- as an alternative to specifying coefficient801names and/or indices, you can give the coefficients themselves as802arbitrary expressions and/or strings. Using strings allows you to803easily add "parameters": the base field of ``self`` will be extended804to include all necessary names.805806OUTPUT:807808- an :class:`anticanonical hypersurface <AnticanonicalHypersurface>` of809``self`` (with the extended base field, if necessary).810811EXAMPLES:812813We realize the projective plane as a Fano toric variety::814815sage: simplex = lattice_polytope.projective_space(2)816sage: P2 = CPRFanoToricVariety(Delta_polar=simplex)817818Its anticanonical "hypersurface" is a one-dimensional Calabi-Yau819manifold::820821sage: P2.anticanonical_hypersurface(822... monomial_points="all")823Closed subscheme of 2-d CPR-Fano toric variety824covered by 3 affine patches defined by:825a0*z0^3 + a9*z0^2*z1 + a7*z0*z1^2826+ a1*z1^3 + a8*z0^2*z2 + a6*z0*z1*z2827+ a4*z1^2*z2 + a5*z0*z2^2828+ a3*z1*z2^2 + a2*z2^3829830In many cases it is sufficient to work with the "simplified polynomial831moduli space" of anticanonical hypersurfaces::832833sage: P2.anticanonical_hypersurface(834... monomial_points="simplified")835Closed subscheme of 2-d CPR-Fano toric variety836covered by 3 affine patches defined by:837a0*z0^3 + a1*z1^3 + a6*z0*z1*z2 + a2*z2^3838839The mirror family to these hypersurfaces lives inside the Fano toric840variety obtained using ``simplex`` as ``Delta`` instead of841``Delta_polar``::842843sage: FTV = CPRFanoToricVariety(Delta=simplex,844... coordinate_points="all")845sage: FTV.anticanonical_hypersurface(846... monomial_points="simplified")847Closed subscheme of 2-d CPR-Fano toric variety848covered by 9 affine patches defined by:849a2*z2^3*z3^2*z4*z5^2*z8850+ a1*z1^3*z3*z4^2*z7^2*z9851+ a3*z0*z1*z2*z3*z4*z5*z7*z8*z9852+ a0*z0^3*z5*z7*z8^2*z9^2853854Here we have taken the resolved version of the ambient space for the855mirror family, but in fact we don't have to resolve singularities856corresponding to the interior points of facets - they are singular857points which do not lie on a generic anticanonical hypersurface::858859sage: FTV = CPRFanoToricVariety(Delta=simplex,860... coordinate_points="all but facets")861sage: FTV.anticanonical_hypersurface(862... monomial_points="simplified")863Closed subscheme of 2-d CPR-Fano toric variety864covered by 3 affine patches defined by:865a0*z0^3 + a1*z1^3 + a3*z0*z1*z2 + a2*z2^3866867This looks very similar to our second anticanonical868hypersurface of the projective plane, as expected, since all869one-dimensional Calabi-Yau manifolds are elliptic curves!870871All anticanonical hypersurfaces constructed above were generic with872automatically generated coefficients. If you want, you can specify your873own names ::874875sage: FTV.anticanonical_hypersurface(876... coefficient_names="a b c d")877Closed subscheme of 2-d CPR-Fano toric variety878covered by 3 affine patches defined by:879a*z0^3 + b*z1^3 + d*z0*z1*z2 + c*z2^3880881or give concrete coefficients ::882883sage: FTV.anticanonical_hypersurface(884... coefficients=[1, 2, 3, 4])885Closed subscheme of 2-d CPR-Fano toric variety886covered by 3 affine patches defined by:887z0^3 + 2*z1^3 + 4*z0*z1*z2 + 3*z2^3888889or even mix numerical coefficients with some expressions ::890891sage: H = FTV.anticanonical_hypersurface(892... coefficients=[0, "t", "1/t", "psi/(psi^2 + phi)"])893sage: H894Closed subscheme of 2-d CPR-Fano toric variety895covered by 3 affine patches defined by:896t*z1^3 + (psi/(psi^2 + phi))*z0*z1*z2 + 1/t*z2^3897sage: R = H.ambient_space().base_ring()898sage: R899Fraction Field of900Multivariate Polynomial Ring in phi, psi, t901over Rational Field902"""903# The example above is also copied to the tutorial section in the904# main documentation of the module.905return AnticanonicalHypersurface(self, **kwds)906907def change_ring(self, F):908r"""909Return a CPR-Fano toric variety over field ``F``, otherwise the same910as ``self``.911912INPUT:913914- ``F`` -- field.915916OUTPUT:917918- :class:`CPR-Fano toric variety <CPRFanoToricVariety_field>` over919``F``.920921.. NOTE::922923There is no need to have any relation between ``F`` and the base924field of ``self``. If you do want to have such a relation, use925:meth:`base_extend` instead.926927EXAMPLES::928929sage: P1xP1 = CPRFanoToricVariety(930... Delta_polar=lattice_polytope.octahedron(2))931sage: P1xP1.base_ring()932Rational Field933sage: P1xP1_RR = P1xP1.change_ring(RR)934sage: P1xP1_RR.base_ring()935Real Field with 53 bits of precision936sage: P1xP1_QQ = P1xP1_RR.change_ring(QQ)937sage: P1xP1_QQ.base_ring()938Rational Field939sage: P1xP1_RR.base_extend(QQ)940Traceback (most recent call last):941...942ValueError: no natural map from the base ring943(=Real Field with 53 bits of precision)944to R (=Rational Field)!945"""946if self.base_ring() == F:947return self948else:949return CPRFanoToricVariety_field(self._Delta_polar, self._fan,950self._coordinate_points, self._point_to_ray,951self.variable_names(), None, F)952# coordinate_name_indices do not matter, we give explicit953# names for all variables954955def coordinate_point_to_coordinate(self, point):956r"""957Return the variable of the coordinate ring corresponding to ``point``.958959INPUT:960961- ``point`` -- integer from the list of :meth:`coordinate_points`.962963OUTPUT:964965- the corresponding generator of the coordinate ring of ``self``.966967EXAMPLES::968969sage: diamond = lattice_polytope.octahedron(2)970sage: FTV = CPRFanoToricVariety(diamond,971... coordinate_points=[0,1,2,3,8])972sage: FTV.coordinate_points()973(0, 1, 2, 3, 8)974sage: FTV.gens()975(z0, z1, z2, z3, z8)976sage: FTV.coordinate_point_to_coordinate(8)977z8978"""979return self.gen(self._point_to_ray[point])980981def coordinate_points(self):982r"""983Return indices of points of :meth:`Delta_polar` used for coordinates.984985OUTPUT:986987- :class:`tuple` of integers.988989EXAMPLES::990991sage: diamond = lattice_polytope.octahedron(2)992sage: square = diamond.polar()993sage: FTV = CPRFanoToricVariety(Delta_polar=square,994... coordinate_points=[0,1,2,3,8])995sage: FTV.coordinate_points()996(0, 1, 2, 3, 8)997sage: FTV.gens()998(z0, z1, z2, z3, z8)9991000sage: FTV = CPRFanoToricVariety(Delta_polar=square,1001... coordinate_points="all")1002sage: FTV.coordinate_points()1003(0, 1, 2, 3, 4, 5, 7, 8)1004sage: FTV.gens()1005(z0, z1, z2, z3, z4, z5, z7, z8)10061007Note that one point is missing, namely ::10081009sage: square.origin()101061011"""1012return self._coordinate_points10131014def Delta(self):1015r"""1016Return the reflexive polytope associated to ``self``.10171018OUTPUT:10191020- reflexive :class:`lattice polytope1021<sage.geometry.lattice_polytope.LatticePolytopeClass>`. The1022underlying fan of ``self`` is a coherent subdivision of the1023*normal fan* of this polytope.10241025EXAMPLES::10261027sage: diamond = lattice_polytope.octahedron(2)1028sage: P1xP1 = CPRFanoToricVariety(Delta_polar=diamond)1029sage: P1xP1.Delta()1030A polytope polar to An octahedron: 2-dimensional, 4 vertices.1031sage: P1xP1.Delta() is diamond.polar()1032True1033"""1034return self._Delta_polar.polar()10351036def Delta_polar(self):1037r"""1038Return polar of :meth:`Delta`.10391040OUTPUT:10411042- reflexive :class:`lattice polytope1043<sage.geometry.lattice_polytope.LatticePolytopeClass>`. The1044underlying fan of ``self`` is a coherent subdivision of the1045*face fan* of this polytope.10461047EXAMPLES::10481049sage: diamond = lattice_polytope.octahedron(2)1050sage: P1xP1 = CPRFanoToricVariety(Delta_polar=diamond)1051sage: P1xP1.Delta_polar()1052An octahedron: 2-dimensional, 4 vertices.1053sage: P1xP1.Delta_polar() is diamond1054True1055sage: P1xP1.Delta_polar() is P1xP1.Delta().polar()1056True1057"""1058return self._Delta_polar10591060def nef_complete_intersection(self, nef_partition, **kwds):1061r"""1062Return a nef complete intersection in ``self``.10631064.. NOTE::10651066The returned complete intersection may be actually a subscheme of1067**another** CPR-Fano toric variety: if the base field of ``self``1068does not include all of the required names for monomial1069coefficients, it will be automatically extended.10701071Below `\Delta` is the reflexive polytope corresponding to ``self``,1072i.e. the fan of ``self`` is a refinement of the normal fan of1073`\Delta`. Other polytopes are described in the documentation of1074:class:`nef-partitions <sage.geometry.lattice_polytope.NefPartition>`1075of :class:`reflexive polytopes1076<sage.geometry.lattice_polytope.LatticePolytopeClass>`.10771078Except for the first argument, ``nef_partition``, this method accepts1079only keyword parameters.10801081INPUT:10821083- ``nef_partition`` -- a `k`-part :class:`nef-partition1084<sage.geometry.lattice_polytope.NefPartition>` of `\Delta^\circ`, all1085other parameters (if given) must be lists of length `k`;10861087- ``monomial_points`` -- the `i`-th element of this list is either a1088list of integers or a string. A list will be interpreted as indices1089of points of `\Delta_i` which should be used for monomials of the1090`i`-th polynomial of this complete intersection. A string must be one1091of the following descriptions of points of `\Delta_i`:10921093* "vertices",1094* "vertices+origin",1095* "all" (default),10961097when using this description, it is also OK to pass a single string as1098``monomial_points`` instead of repeating it `k` times;10991100- ``coefficient_names`` -- the `i`-th element of this list specifies1101names for the monomial coefficients of the `i`-th polynomial, see1102:func:`~sage.schemes.toric.variety.normalize_names`1103for acceptable formats. If not given, indexed coefficient names will1104be created automatically;11051106- ``coefficient_name_indices`` -- the `i`-th element of this list1107specifies indices for indexed coefficients of the `i`-th polynomial.1108If not given, the index of each coefficient will coincide with the1109index of the corresponding point of `\Delta_i`;11101111- ``coefficients`` -- as an alternative to specifying coefficient1112names and/or indices, you can give the coefficients themselves as1113arbitrary expressions and/or strings. Using strings allows you to1114easily add "parameters": the base field of ``self`` will be extended1115to include all necessary names.11161117OUTPUT:11181119- a :class:`nef complete intersection <NefCompleteIntersection>` of1120``self`` (with the extended base field, if necessary).11211122EXAMPLES:11231124We construct several complete intersections associated to the same1125nef-partition of the 3-dimensional reflexive polytope #2254::11261127sage: p = ReflexivePolytope(3, 2254) # long time (7s on sage.math, 2011)1128sage: np = p.nef_partitions()[1] # long time1129sage: np # long time1130Nef-partition {2, 3, 4, 7, 8} U {0, 1, 5, 6}1131sage: X = CPRFanoToricVariety(Delta_polar=p) # long time1132sage: X.nef_complete_intersection(np) # long time1133Closed subscheme of 3-d CPR-Fano toric variety1134covered by 10 affine patches defined by:1135a2*z1*z4^2*z5^2*z7^3 + a1*z2*z4*z5*z6*z7^2*z8^21136+ a3*z2*z3*z4*z7*z8 + a0*z0*z2,1137b2*z1*z4*z5^2*z6^2*z7^2*z8^2 + b0*z2*z5*z6^3*z7*z8^41138+ b5*z1*z3*z4*z5*z6*z7*z8 + b3*z2*z3*z6^2*z8^31139+ b1*z1*z3^2*z4 + b4*z0*z1*z5*z611401141Now we include only monomials associated to vertices of `\Delta_i`::11421143sage: X.nef_complete_intersection(np, monomial_points="vertices") # long time1144Closed subscheme of 3-d CPR-Fano toric variety1145covered by 10 affine patches defined by:1146a2*z1*z4^2*z5^2*z7^3 + a1*z2*z4*z5*z6*z7^2*z8^21147+ a3*z2*z3*z4*z7*z8 + a0*z0*z2,1148b2*z1*z4*z5^2*z6^2*z7^2*z8^2 + b0*z2*z5*z6^3*z7*z8^41149+ b3*z2*z3*z6^2*z8^3 + b1*z1*z3^2*z4 + b4*z0*z1*z5*z611501151(effectively, we set ``b5=0``). Next we provide coefficients explicitly1152instead of using default generic names::11531154sage: X.nef_complete_intersection(np, # long time1155... monomial_points="vertices",1156... coefficients=[("a", "a^2", "a/e", "c_i"), range(1,6)])1157Closed subscheme of 3-d CPR-Fano toric variety1158covered by 10 affine patches defined by:1159a/e*z1*z4^2*z5^2*z7^3 + a^2*z2*z4*z5*z6*z7^2*z8^21160+ c_i*z2*z3*z4*z7*z8 + a*z0*z2,11613*z1*z4*z5^2*z6^2*z7^2*z8^2 + z2*z5*z6^3*z7*z8^41162+ 4*z2*z3*z6^2*z8^3 + 2*z1*z3^2*z4 + 5*z0*z1*z5*z611631164Finally, we take a look at the generic representative of these complete1165intersections in a completely resolved ambient toric variety::11661167sage: X = CPRFanoToricVariety(Delta_polar=p, # long time1168... coordinate_points="all")1169sage: X.nef_complete_intersection(np) # long time1170Closed subscheme of 3-d CPR-Fano toric variety1171covered by 22 affine patches defined by:1172a1*z2*z4*z5*z6*z7^2*z8^2*z9^2*z10^2*z11*z12*z131173+ a2*z1*z4^2*z5^2*z7^3*z9*z10^2*z12*z131174+ a3*z2*z3*z4*z7*z8*z9*z10*z11*z12 + a0*z0*z2,1175b0*z2*z5*z6^3*z7*z8^4*z9^3*z10^2*z11^2*z12*z13^21176+ b2*z1*z4*z5^2*z6^2*z7^2*z8^2*z9^2*z10^2*z11*z12*z13^21177+ b3*z2*z3*z6^2*z8^3*z9^2*z10*z11^2*z12*z131178+ b5*z1*z3*z4*z5*z6*z7*z8*z9*z10*z11*z12*z131179+ b1*z1*z3^2*z4*z11*z12 + b4*z0*z1*z5*z6*z131180"""1181return NefCompleteIntersection(self, nef_partition, **kwds)11821183def cartesian_product(self, other,1184coordinate_names=None, coordinate_indices=None):1185r"""1186Return the Cartesian product of ``self`` with ``other``.11871188INPUT:11891190- ``other`` -- a (possibly1191:class:`CPR-Fano <CPRFanoToricVariety_field>`) :class:`toric variety1192<sage.schemes.toric.variety.ToricVariety_field>`;11931194- ``coordinate_names`` -- names of variables for the coordinate ring,1195see :func:`normalize_names` for acceptable formats. If not given,1196indexed variable names will be created automatically;11971198- ``coordinate_indices`` -- list of integers, indices for indexed1199variables. If not given, the index of each variable will coincide1200with the index of the corresponding ray of the fan.12011202OUTPUT:12031204- a :class:`toric variety1205<sage.schemes.toric.variety.ToricVariety_field>`, which is1206:class:`CPR-Fano <CPRFanoToricVariety_field>` if ``other`` was.12071208EXAMPLES::12091210sage: P1 = toric_varieties.P1()1211sage: P2 = toric_varieties.P2()1212sage: P1xP2 = P1.cartesian_product(P2); P1xP212133-d CPR-Fano toric variety covered by 6 affine patches1214sage: P1xP2.fan().rays()1215N+N( 1, 0, 0),1216N+N(-1, 0, 0),1217N+N( 0, 1, 0),1218N+N( 0, 0, 1),1219N+N( 0, -1, -1)1220in 3-d lattice N+N1221sage: P1xP2.Delta_polar()1222A lattice polytope: 3-dimensional, 5 vertices.1223"""1224if is_CPRFanoToricVariety(other):1225fan = self.fan().cartesian_product(other.fan())1226Delta_polar = LatticePolytope(fan.rays())12271228points = Delta_polar.points().columns()1229point_to_ray = dict()1230coordinate_points = []1231for ray_index, ray in enumerate(fan.rays()):1232point = points.index(ray)1233coordinate_points.append(point)1234point_to_ray[point] = ray_index12351236return CPRFanoToricVariety_field(Delta_polar, fan,1237coordinate_points, point_to_ray,1238coordinate_names, coordinate_indices,1239self.base_ring())1240return super(CPRFanoToricVariety_field, self).cartesian_product(other)12411242def resolve(self, **kwds):1243r"""1244Construct a toric variety whose fan subdivides the fan of ``self``.12451246This function accepts only keyword arguments, none of which are1247mandatory.12481249INPUT:12501251- ``new_points`` -- list of integers, indices of boundary points of1252:meth:`Delta_polar`, which should be added as rays to the1253subdividing fan;12541255- all other arguments will be passed to1256:meth:`~sage.schemes.toric.variety.ToricVariety_field.resolve`1257method of (general) toric varieties, see its documentation for1258details.12591260OUTPUT:12611262- :class:`CPR-Fano toric variety <CPRFanoToricVariety_field>` if there1263was no ``new_rays`` argument and :class:`toric variety1264<sage.schemes.toric.variety.ToricVariety_field>` otherwise.12651266EXAMPLES::12671268sage: diamond = lattice_polytope.octahedron(2)1269sage: FTV = CPRFanoToricVariety(Delta=diamond)1270sage: FTV.coordinate_points()1271(0, 1, 2, 3)1272sage: FTV.gens()1273(z0, z1, z2, z3)1274sage: FTV_res = FTV.resolve(new_points=[6,8])1275Traceback (most recent call last):1276...1277ValueError: the origin (point #6)1278cannot be used for subdivision!1279sage: FTV_res = FTV.resolve(new_points=[8,5])1280sage: FTV_res12812-d CPR-Fano toric variety covered by 6 affine patches1282sage: FTV_res.coordinate_points()1283(0, 1, 2, 3, 8, 5)1284sage: FTV_res.gens()1285(z0, z1, z2, z3, z8, z5)12861287sage: TV_res = FTV.resolve(new_rays=[(1,2)])1288sage: TV_res12892-d toric variety covered by 5 affine patches1290sage: TV_res.gens()1291(z0, z1, z2, z3, z4)1292"""1293# Reasons to override the base class:1294# - allow using polytope point indices for subdivision1295# - handle automatic name creation in a different fashion1296# - return CPR-Fano toric variety if the above feature was used and1297# just toric variety if subdivision involves rays1298if "new_rays" in kwds:1299if "new_points" in kwds:1300raise ValueError("you cannot give new_points and new_rays at "1301"the same time!")1302return super(CPRFanoToricVariety_field, self).resolve(**kwds)1303# Now we need to construct another Fano variety1304new_points = kwds.pop("new_points", ())1305coordinate_points = self.coordinate_points()1306new_points = tuple(point for point in new_points1307if point not in coordinate_points)1308Delta_polar = self._Delta_polar1309if Delta_polar.origin() in new_points:1310raise ValueError("the origin (point #%d) cannot be used for "1311"subdivision!" % Delta_polar.origin())1312if new_points:1313coordinate_points = coordinate_points + new_points1314point_to_ray = dict()1315for n, point in enumerate(coordinate_points):1316point_to_ray[point] = n1317else:1318point_to_ray = self._point_to_ray1319new_rays = [Delta_polar.point(point) for point in new_points]1320coordinate_name_indices = kwds.pop("coordinate_name_indices",1321coordinate_points)1322fan = self.fan()1323if "coordinate_names" in kwds:1324coordinate_names = kwds.pop("coordinate_names")1325else:1326coordinate_names = list(self.variable_names())1327coordinate_names.extend(normalize_names(ngens=len(new_rays),1328indices=coordinate_name_indices[fan.nrays():],1329prefix=self._coordinate_prefix))1330coordinate_names.append(self._coordinate_prefix + "+")1331rfan = fan.subdivide(new_rays=new_rays, **kwds)1332resolution = CPRFanoToricVariety_field(Delta_polar, rfan,1333coordinate_points, point_to_ray, coordinate_names,1334coordinate_name_indices, self.base_ring())1335R = self.coordinate_ring()1336R_res = resolution.coordinate_ring()1337resolution_map = resolution.hom(R.hom(R_res.gens()[:R.ngens()]), self)1338resolution._resolution_map = resolution_map1339return resolution134013411342class AnticanonicalHypersurface(AlgebraicScheme_subscheme_toric):1343r"""1344Construct an anticanonical hypersurface of a CPR-Fano toric variety.13451346INPUT:13471348- ``P_Delta`` -- :class:`CPR-Fano toric variety1349<CPRFanoToricVariety_field>` associated to a reflexive polytope1350`\Delta`;13511352- see :meth:`CPRFanoToricVariety_field.anticanonical_hypersurface` for1353documentation on all other acceptable parameters.13541355OUTPUT:13561357- :class:`anticanonical hypersurface <AnticanonicalHypersurface>` of1358``P_Delta`` (with the extended base field, if necessary).13591360EXAMPLES::13611362sage: P1xP1 = CPRFanoToricVariety(1363... Delta_polar=lattice_polytope.octahedron(2))1364sage: import sage.schemes.toric.fano_variety as ftv1365sage: ftv.AnticanonicalHypersurface(P1xP1)1366Closed subscheme of 2-d CPR-Fano toric variety1367covered by 4 affine patches defined by:1368a1*z0^2*z1^2 + a0*z1^2*z2^2 + a6*z0*z1*z2*z31369+ a3*z0^2*z3^2 + a2*z2^2*z3^213701371See :meth:`~CPRFanoToricVariety_field.anticanonical_hypersurface()` for a1372more elaborate example.1373"""1374def __init__(self, P_Delta, monomial_points=None, coefficient_names=None,1375coefficient_name_indices=None, coefficients=None):1376r"""1377See :meth:`CPRFanoToricVariety_field.anticanonical_hypersurface` for1378documentation.13791380TESTS::13811382sage: P1xP1 = CPRFanoToricVariety(1383... Delta_polar=lattice_polytope.octahedron(2))1384sage: import sage.schemes.toric.fano_variety as ftv1385sage: ftv.AnticanonicalHypersurface(P1xP1)1386Closed subscheme of 2-d CPR-Fano toric variety1387covered by 4 affine patches defined by:1388a1*z0^2*z1^2 + a0*z1^2*z2^2 + a6*z0*z1*z2*z31389+ a3*z0^2*z3^2 + a2*z2^2*z3^213901391Check that finite fields are handled correctly :trac:`14899`::13921393sage: F = GF(5^2, "a")1394sage: X = P1xP1.change_ring(F)1395sage: X.anticanonical_hypersurface(monomial_points="all",1396... coefficients=[1]*X.Delta().npoints())1397Closed subscheme of 2-d CPR-Fano toric variety1398covered by 4 affine patches defined by:1399z0^2*z1^2 + z0*z1^2*z2 + z1^2*z2^2 + z0^2*z1*z3 + z0*z1*z2*z31400+ z1*z2^2*z3 + z0^2*z3^2 + z0*z2*z3^2 + z2^2*z3^21401"""1402if not is_CPRFanoToricVariety(P_Delta):1403raise TypeError("anticanonical hypersurfaces can only be "1404"constructed for CPR-Fano toric varieties!"1405"\nGot: %s" % P_Delta)1406Delta = P_Delta.Delta()1407Delta_polar = Delta.polar()1408# Monomial points normalization1409if monomial_points == "vertices":1410monomial_points = range(Delta.nvertices())1411elif monomial_points == "all":1412monomial_points = range(Delta.npoints())1413elif monomial_points == "vertices+origin":1414monomial_points = range(Delta.nvertices())1415monomial_points.append(Delta.origin())1416elif monomial_points == "simplified" or monomial_points is None:1417monomial_points = Delta.skeleton_points(Delta.dim() - 2)1418monomial_points.append(Delta.origin())1419elif isinstance(monomial_points, str):1420raise ValueError("%s is an unsupported description of monomial "1421"points!" % monomial_points)1422monomial_points = tuple(monomial_points)1423self._monomial_points = monomial_points1424# Make the necessary ambient space1425if coefficients is None:1426if coefficient_name_indices is None:1427coefficient_name_indices = monomial_points1428coefficient_names = normalize_names(1429coefficient_names, len(monomial_points),1430DEFAULT_COEFFICIENT, coefficient_name_indices)1431# We probably don't want it: the analog in else-branch is unclear.1432# self._coefficient_names = coefficient_names1433F = add_variables(P_Delta.base_ring(), coefficient_names)1434coefficients = [F(coef) for coef in coefficient_names]1435else:1436variables = set()1437nonstr = []1438regex = re.compile("[_A-Za-z]\w*")1439for c in coefficients:1440if isinstance(c, str):1441variables.update(regex.findall(c))1442else:1443nonstr.append(c)1444F = add_variables(P_Delta.base_ring(), sorted(variables))1445F = get_coercion_model().common_parent(F, *nonstr)1446coefficients = map(F, coefficients)1447P_Delta = P_Delta.base_extend(F)1448if len(monomial_points) != len(coefficients):1449raise ValueError("cannot construct equation of the anticanonical"1450" hypersurface with %d monomials and %d coefficients"1451% (len(monomial_points), len(coefficients)))1452# Defining polynomial1453h = sum(coef * prod(P_Delta.coordinate_point_to_coordinate(n)1454** (Delta.point(m) * Delta_polar.point(n) + 1)1455for n in P_Delta.coordinate_points())1456for m, coef in zip(monomial_points, coefficients))1457super(AnticanonicalHypersurface, self).__init__(P_Delta, h)145814591460class NefCompleteIntersection(AlgebraicScheme_subscheme_toric):1461r"""1462Construct a nef complete intersection in a CPR-Fano toric variety.14631464INPUT:14651466- ``P_Delta`` -- a :class:`CPR-Fano toric variety1467<CPRFanoToricVariety_field>` associated to a reflexive polytope1468`\Delta`;14691470- see :meth:`CPRFanoToricVariety_field.nef_complete_intersection` for1471documentation on all other acceptable parameters.14721473OUTPUT:14741475- a :class:`nef complete intersection <NefCompleteIntersection>` of1476``P_Delta`` (with the extended base field, if necessary).14771478EXAMPLES::14791480sage: o = lattice_polytope.octahedron(3)1481sage: np = o.nef_partitions()[0]1482sage: np1483Nef-partition {0, 1, 3} U {2, 4, 5}1484sage: X = CPRFanoToricVariety(Delta_polar=o)1485sage: X.nef_complete_intersection(np)1486Closed subscheme of 3-d CPR-Fano toric variety1487covered by 8 affine patches defined by:1488a1*z0^2*z1 + a4*z0*z1*z3 + a3*z1*z3^21489+ a0*z0^2*z4 + a5*z0*z3*z4 + a2*z3^2*z4,1490b0*z1*z2^2 + b1*z2^2*z4 + b4*z1*z2*z51491+ b5*z2*z4*z5 + b3*z1*z5^2 + b2*z4*z5^214921493See :meth:`CPRFanoToricVariety_field.nef_complete_intersection` for a1494more elaborate example.1495"""1496def __init__(self, P_Delta, nef_partition,1497monomial_points="all", coefficient_names=None,1498coefficient_name_indices=None, coefficients=None):1499r"""1500See :meth:`CPRFanoToricVariety_field.nef_complete_intersection` for1501documentation.15021503TESTS::15041505sage: o = lattice_polytope.octahedron(3)1506sage: np = o.nef_partitions()[0]1507sage: np1508Nef-partition {0, 1, 3} U {2, 4, 5}1509sage: X = CPRFanoToricVariety(Delta_polar=o)1510sage: from sage.schemes.toric.fano_variety import *1511sage: NefCompleteIntersection(X, np)1512Closed subscheme of 3-d CPR-Fano toric variety1513covered by 8 affine patches defined by:1514a1*z0^2*z1 + a4*z0*z1*z3 + a3*z1*z3^21515+ a0*z0^2*z4 + a5*z0*z3*z4 + a2*z3^2*z4,1516b0*z1*z2^2 + b1*z2^2*z4 + b4*z1*z2*z51517+ b5*z2*z4*z5 + b3*z1*z5^2 + b2*z4*z5^21518"""1519if not is_CPRFanoToricVariety(P_Delta):1520raise TypeError("nef complete intersections can only be "1521"constructed for CPR-Fano toric varieties!"1522"\nGot: %s" % P_Delta)1523if nef_partition.Delta() is not P_Delta.Delta():1524raise ValueError("polytopes 'Delta' of the nef-partition and the "1525"CPR-Fano toric variety must be the same!")1526self._nef_partition = nef_partition1527k = nef_partition.nparts()1528# Pre-normalize all parameters1529if isinstance(monomial_points, str):1530monomial_points = [monomial_points] * k1531if coefficient_names is None:1532coefficient_names = [None] * k1533if coefficient_name_indices is None:1534coefficient_name_indices = [None] * k1535if coefficients is None:1536coefficients = [None] * k15371538polynomials = []1539Delta_polar = P_Delta.Delta_polar()1540for i in range(k):1541Delta_i = nef_partition.Delta(i)1542# Monomial points normalization1543if monomial_points[i] == "vertices":1544monomial_points[i] = range(Delta_i.nvertices())1545elif monomial_points[i] == "all":1546monomial_points[i] = range(Delta_i.npoints())1547elif monomial_points[i] == "vertices+origin":1548monomial_points[i] = range(Delta_i.nvertices())1549if (Delta_i.origin() is not None1550and Delta_i.origin() >= Delta_i.nvertices()):1551monomial_points[i].append(Delta_i.origin())1552elif isinstance(monomial_points[i], str):1553raise ValueError("'%s' is an unsupported description of "1554"monomial points!" % monomial_points[i])1555monomial_points[i] = tuple(monomial_points[i])1556# Extend the base ring of the ambient space if necessary1557if coefficients[i] is None:1558if coefficient_name_indices[i] is None:1559coefficient_name_indices[i] = monomial_points[i]1560coefficient_names[i] = normalize_names(1561coefficient_names[i], len(monomial_points[i]),1562DEFAULT_COEFFICIENTS[i], coefficient_name_indices[i])1563F = add_variables(P_Delta.base_ring(), coefficient_names[i])1564coefficients[i] = [F(coef) for coef in coefficient_names[i]]1565else:1566variables = set()1567nonstr = []1568regex = re.compile("[_A-Za-z]\w*")1569for c in coefficients[i]:1570if isinstance(c, str):1571variables.update(regex.findall(c))1572else:1573nonstr.append(c)1574F = add_variables(P_Delta.base_ring(), sorted(variables))1575F = get_coercion_model().common_parent(F, *nonstr)1576coefficients[i] = map(F, coefficients[i])1577P_Delta = P_Delta.base_extend(F)1578if len(monomial_points[i]) != len(coefficients[i]):1579raise ValueError("cannot construct equation %d of the complete"1580" intersection with %d monomials and %d coefficients"1581% (i, len(monomial_points[i]), len(coefficients[i])))1582# Defining polynomial1583h = sum(coef * prod(P_Delta.coordinate_point_to_coordinate(n)1584** (Delta_i.point(m) * Delta_polar.point(n)1585+ (nef_partition.part_of_point(n) == i))1586for n in P_Delta.coordinate_points())1587for m, coef in zip(monomial_points[i], coefficients[i]))1588polynomials.append(h)1589self._monomial_points = tuple(monomial_points)1590super(NefCompleteIntersection, self).__init__(P_Delta, polynomials)15911592def nef_partition(self):1593r"""1594Return the nef-partition associated to ``self``.15951596OUTPUT:15971598- a :class:`nef-partition1599<sage.geometry.lattice_polytope.NefPartition>`.16001601EXAMPLES::16021603sage: o = lattice_polytope.octahedron(3)1604sage: np = o.nef_partitions()[0]1605sage: np1606Nef-partition {0, 1, 3} U {2, 4, 5}1607sage: X = CPRFanoToricVariety(Delta_polar=o)1608sage: CI = X.nef_complete_intersection(np)1609sage: CI1610Closed subscheme of 3-d CPR-Fano toric variety1611covered by 8 affine patches defined by:1612a1*z0^2*z1 + a4*z0*z1*z3 + a3*z1*z3^21613+ a0*z0^2*z4 + a5*z0*z3*z4 + a2*z3^2*z4,1614b0*z1*z2^2 + b1*z2^2*z4 + b4*z1*z2*z51615+ b5*z2*z4*z5 + b3*z1*z5^2 + b2*z4*z5^21616sage: CI.nef_partition()1617Nef-partition {0, 1, 3} U {2, 4, 5}1618sage: CI.nef_partition() is np1619True1620"""1621return self._nef_partition162216231624def add_variables(field, variables):1625r"""1626Extend ``field`` to include all ``variables``.16271628INPUT:16291630- ``field`` - a field;16311632- ``variables`` - a list of strings.16331634OUTPUT:16351636- a fraction field extending the original ``field``, which has all1637``variables`` among its generators.16381639EXAMPLES:16401641We start with the rational field and slowly add more variables::16421643sage: from sage.schemes.toric.fano_variety import *1644sage: F = add_variables(QQ, []); F # No extension1645Rational Field1646sage: F = add_variables(QQ, ["a"]); F1647Fraction Field of Univariate Polynomial Ring1648in a over Rational Field1649sage: F = add_variables(F, ["a"]); F1650Fraction Field of Univariate Polynomial Ring1651in a over Rational Field1652sage: F = add_variables(F, ["b", "c"]); F1653Fraction Field of Multivariate Polynomial Ring1654in a, b, c over Rational Field1655sage: F = add_variables(F, ["c", "d", "b", "c", "d"]); F1656Fraction Field of Multivariate Polynomial Ring1657in a, b, c, d over Rational Field1658"""1659if not variables:1660return field1661if is_FractionField(field):1662# Q(a) ---> Q(a, b) rather than Q(a)(b)1663R = field.ring()1664if is_PolynomialRing(R) or is_MPolynomialRing(R):1665new_variables = list(R.variable_names())1666for v in variables:1667if v not in new_variables:1668new_variables.append(v)1669if len(new_variables) > R.ngens():1670return PolynomialRing(R.base_ring(),1671new_variables).fraction_field()1672else:1673return field1674# "Intelligent extension" didn't work, use the "usual one."1675new_variables = []1676for v in variables:1677if v not in new_variables:1678new_variables.append(v)1679return PolynomialRing(field, new_variables).fraction_field()1680168116821683