Ticket #12892: trac_12892_toric_morphism_fibers.patch

File trac_12892_toric_morphism_fibers.patch, 26.2 KB (added by Volker Braun, 9 years ago)

Updated patch

  • sage/geometry/fan_morphism.py

    # HG changeset patch
    # User Volker Braun <vbraun@stp.dias.ie>
    # Date 1372033114 14400
    #      Sun Jun 23 20:18:34 2013 -0400
    # Node ID c24d8f842689edc4db10e9dd3f8ae088de12347f
    # Parent  3244235f697849a3339abe0fd199eb975e11adb8
    Trac #12892: Toric fibration morphisms
    
    Note that the fiber of a toric morphism is a reducible union
    of (irreducible) toric varieties. This patch implements the embedding
    of fiber components as a scheme morphism.
    
    diff --git a/sage/geometry/fan_morphism.py b/sage/geometry/fan_morphism.py
    a b  
    677677        chambers = None # preimages of codomain cones, computed if necessary
    678678        new_cones = []
    679679        for cone_index, domain_cone in enumerate(domain_fan):
    680             if reduce(operator.and_, (RISGIS[i]
    681                                 for i in domain_cone.ambient_ray_indices())):
     680            if reduce(operator.and_,
     681                      (RISGIS[i] for i in domain_cone.ambient_ray_indices())):
    682682                # There is a codomain cone containing all rays of this domain
    683683                # cone, no need to subdivide it.
    684684                new_cones.append(domain_cone)
     
    848848            Rational polyhedral fan in 3-d lattice N3
    849849            into the support of
    850850            Rational polyhedral fan in 2-d lattice N2!
     851
     852
     853        TESTS::
     854
     855            sage: trivialfan2 = Fan([],[],lattice=ToricLattice(2))
     856            sage: trivialfan3 = Fan([],[],lattice=ToricLattice(3))
     857            sage: FanMorphism(zero_matrix(2,3), trivialfan2, trivialfan3)
     858            Fan morphism defined by the matrix
     859            [0 0 0]
     860            [0 0 0]
     861            Domain fan: Rational polyhedral fan in 2-d lattice N
     862            Codomain fan: Rational polyhedral fan in 3-d lattice N
    851863        """
    852864        domain_fan = self._domain_fan
    853865        if domain_fan.lattice() is not self.domain():
     
    859871                             % (codomain_fan, self.codomain()))
    860872        RISGIS = self._RISGIS()
    861873        for n, domain_cone in enumerate(domain_fan):
    862             if not reduce(operator.and_,
    863                 (RISGIS[i] for i in domain_cone.ambient_ray_indices())):
     874            if not domain_cone.is_trivial() and \
     875                    not reduce(operator.and_,
     876                               (RISGIS[i] for i in domain_cone.ambient_ray_indices())):
    864877                raise ValueError("the image of generating cone #%d of the "
    865878                                 "domain fan is not contained in a single "
    866879                                 "cone of the codomain fan!" % n)
     
    18281841                            check=False)
    18291842        phi_i = FanMorphism(L.basis_matrix(), Sigma_i, Sigma_prime, check=False)
    18301843        return (phi_i, phi_b, phi_s)
     1844
     1845    def relative_star_generators(self, domain_cone):
     1846        """
     1847        Returns the relative star of ``domain_cone``.
     1848
     1849        EXAMPLES::
     1850
     1851            sage: A2 = toric_varieties.A(2).fan()
     1852            sage: Bl = A2.subdivide([(1,1)])
     1853            sage: f = FanMorphism(identity_matrix(2), Bl, A2)
     1854            sage: for c1 in Bl(1):
     1855            ...       print f.relative_star_generators(c1)
     1856            (1-d cone of Rational polyhedral fan in 2-d lattice N,)
     1857            (1-d cone of Rational polyhedral fan in 2-d lattice N,)
     1858            (2-d cone of Rational polyhedral fan in 2-d lattice N,
     1859             2-d cone of Rational polyhedral fan in 2-d lattice N)
     1860        """
     1861        base_cone = self.image_cone(domain_cone)
     1862        preimg_fan = self.preimage_fan(base_cone)
     1863        return preimg_fan.embed(domain_cone).star_generators()
  • sage/schemes/toric/morphism.py

    diff --git a/sage/schemes/toric/morphism.py b/sage/schemes/toric/morphism.py
    a b  
    169169
    170170from sage.structure.sequence  import Sequence
    171171from sage.rings.all import ZZ
     172from sage.misc.all import cached_method
     173from sage.matrix.constructor import matrix, block_matrix, zero_matrix, identity_matrix
     174from sage.modules.free_module_element import vector
     175from sage.geometry.cone import Cone
     176from sage.geometry.fan import Fan
    172177
    173178from sage.schemes.generic.scheme import is_Scheme     
    174179from sage.schemes.generic.morphism import (
     
    247252            X.codomain()._check_satisfies_equations(coordinates)
    248253        self._coords = coordinates
    249254
    250 
     255       
    251256
    252257############################################################################
    253258# A morphism of toric varieties determined by homogeneous polynomials.
     
    364369    .. WARNING::
    365370
    366371        You should not create objects of this class directly. Use the
    367         :meth:`~sage.schemes.generic.toric_variety.ToricVariety_field.orbit_closure`
     372        :meth:`~sage.schemes.toric.variety.ToricVariety_field.orbit_closure`
    368373        method of :class:`toric varieties
    369         <sage.schemes.generic.toric_variety.ToricVariety_field>`
     374        <sage.schemes.toric.variety.ToricVariety_field>`
    370375        instead.
    371376
    372377    EXAMPLES::
     
    874879                polys[i] *= x**d
    875880        return SchemeMorphism_polynomial_toric_variety(self.parent(), polys)
    876881
     882    def is_bundle(self):
     883        r"""
     884        Check if ``self`` is a bundle.
     885
     886        See :meth:`~sage.geometry.fan_morphism.FanMorphism.is_bundle`
     887        for details.
     888       
     889        OUTPUT:
     890       
     891        - ``True`` if ``self`` is a bundle, ``False`` otherwise.
     892
     893        EXAMPLES::
     894
     895            sage: P1xP1 = toric_varieties.P1xP1()
     896            sage: P1 = toric_varieties.P1()
     897            sage: P1xP1.hom(matrix([[1],[0]]), P1).is_bundle()
     898            True
     899        """
     900        return self.fan_morphism().is_bundle()
     901       
     902    def is_fibration(self):
     903        r"""
     904        Check if ``self`` is a fibration.
     905       
     906        See
     907        :meth:`~sage.geometry.fan_morphism.FanMorphism.is_fibration`
     908        for details.
     909       
     910        OUTPUT:
     911       
     912        - ``True`` if ``self`` is a fibration, ``False`` otherwise.
     913       
     914        EXAMPLES::
     915
     916            sage: P1xP1 = toric_varieties.P1xP1()
     917            sage: P1 = toric_varieties.P1()
     918            sage: P1xP1.hom(matrix([[1],[0]]), P1).is_fibration()
     919            True
     920        """
     921        return self.fan_morphism().is_fibration()
     922
     923    def is_injective(self):
     924        r"""
     925        Check if ``self`` is injective.
     926
     927        See
     928        :meth:`~sage.geometry.fan_morphism.FanMorphism.is_injective`
     929        for details.
     930
     931        OUTPUT:
     932       
     933        - ``True`` if ``self`` is injective, ``False`` otherwise.
     934       
     935        EXAMPLES::
     936
     937            sage: P1xP1 = toric_varieties.P1xP1()
     938            sage: P1 = toric_varieties.P1()
     939            sage: P1xP1.hom(matrix([[1],[0]]), P1).is_injective()
     940            False
     941        """
     942        return self.fan_morphism().is_injective()
     943
     944    def is_surjective(self):
     945        r"""
     946        Check if ``self`` is surjective.
     947       
     948        See
     949        :meth:`~sage.geometry.fan_morphism.FanMorphism.is_surjective`
     950        for details.
     951
     952        OUTPUT:
     953       
     954        - ``True`` if ``self`` is surjective, ``False`` otherwise.
     955       
     956        EXAMPLES::
     957
     958            sage: P1xP1 = toric_varieties.P1xP1()
     959            sage: P1 = toric_varieties.P1()
     960            sage: P1xP1.hom(matrix([[1],[0]]), P1).is_surjective()
     961            True
     962        """
     963        return self.fan_morphism().is_surjective()
     964
     965    @cached_method
     966    def fiber(self):
     967        """
     968        Return a connected component of the generic fiber of the
     969        morphism.
     970       
     971        Note that the fiber of a toric morphism is constant over the
     972        maximal torus, so it makes sense to talk about the "generic"
     973        fiber even if the morphism is not surjective. This method
     974        returns the fiber over the base point with homogeneous
     975        coordinates `[1:1:\cdots:1]`.
     976
     977        The embedding of the generic fiber is a toric morphism. By
     978        contrast, the embedding of the fiber over lower-dimensional
     979        torus orbits of the codomain is not a toric morphism. Use
     980        :meth:`fiber_component` for the latter (non-generic) fibers.
     981
     982        EXAMPLES::
     983
     984            sage: P1xP1 = toric_varieties.P1xP1()
     985            sage: P1 = toric_varieties.P1()
     986            sage: fiber = P1xP1.hom(matrix([[1],[0]]), P1).fiber()
     987            sage: fiber
     988            1-d toric variety covered by 2 affine patches
     989            sage: f = fiber.embedding_morphism();  f
     990            Scheme morphism:
     991              From: 1-d toric variety covered by 2 affine patches
     992              To:   2-d CPR-Fano toric variety covered by 4 affine patches
     993              Defn: Defined by sending Rational polyhedral fan in 1-d lattice N to
     994                    Rational polyhedral fan in 2-d lattice N.
     995            sage: f.as_polynomial_map()
     996            Scheme morphism:
     997              From: 1-d toric variety covered by 2 affine patches
     998              To:   2-d CPR-Fano toric variety covered by 4 affine patches
     999              Defn: Defined on coordinates by sending [z0 : z1] to
     1000                    [1 : 1 : z0 : z1]
     1001
     1002            sage: A1 = toric_varieties.A1()
     1003            sage: fan = Fan([(0,1,2)], [(1,1,0),(1,0,1),(1,-1,-1)]).subdivide(new_rays=[(1,0,0)])
     1004            sage: f = ToricVariety(fan).hom(matrix([[1],[0],[0]]), A1)
     1005            sage: f.fiber()
     1006            2-d affine toric variety
     1007            sage: f.fiber().fan().cones()
     1008            ((0-d cone of Rational polyhedral fan in 2-d lattice N,),)
     1009        """
     1010        from sage.schemes.toric.variety import ToricVariety
     1011        from sage.geometry.toric_lattice import ToricLattice
     1012        fm = self.fan_morphism()
     1013
     1014        # The ker_fan is in a sublattice which does not work yet;
     1015        # rewrite the fan to use a generic lattice
     1016        ker_fan = fm.kernel_fan()
     1017        K = ker_fan.lattice()
     1018        rays = []
     1019        N = ToricLattice(K.dimension())
     1020        for r in ker_fan.rays():
     1021            ray = N(K.echelon_coordinates(r))
     1022            ray.set_immutable()
     1023            rays.append(ray)
     1024        cones = []
     1025        for c in ker_fan.generating_cones():
     1026            cones.append([ker_fan.rays().index(r) for r in c.rays()])
     1027        fiber_fan = Fan(cones, rays, lattice=N)
     1028        fiber = ToricVariety(fiber_fan)
     1029
     1030        from sage.geometry.fan_morphism import FanMorphism
     1031        fan_embedding = FanMorphism(K.echelonized_basis_matrix(), fiber_fan, self.domain().fan())
     1032        homset = fiber.Hom(self.domain())
     1033        embedding = SchemeMorphism_fan_toric_variety(homset, fan_embedding)
     1034        fiber._embedding_morphism = embedding
     1035        return embedding.domain()
     1036             
     1037    def fiber_component(self, domain_cone):
     1038        r"""
     1039        Return the torus orbit closure in the fiber corresponding to
     1040        ``domain_cone``.
     1041
     1042        EXAMPLES::
     1043       
     1044            sage: polytope = Polyhedron(
     1045            ...       [(-3,0,-1,-1),(-1,2,-1,-1),(0,-1,0,0),(0,0,0,1),(0,0,1,0),
     1046            ...        (0,1,0,0),(0,2,-1,-1),(1,0,0,0),(2,0,-1,-1)])
     1047            sage: coarse_fan = FaceFan(polytope.lattice_polytope())
     1048            sage: P2 = toric_varieties.P2()
     1049            sage: proj24 = matrix([[0,0],[1,0],[0,0],[0,1]])
     1050            sage: fm = FanMorphism(proj24, coarse_fan, P2.fan(), subdivide=True)
     1051            sage: fibration = ToricVariety(fm.domain_fan()).hom(fm, P2)
     1052            sage: primitive_cones = fibration.fan_morphism().primitive_preimage_cones(P2.fan(1)[0])
     1053            sage: primitive_cone = primitive_cones[0]
     1054            sage: fibration.fiber_component(primitive_cone)
     1055            2-d toric variety covered by 4 affine patches
     1056           
     1057            sage: for primitive_cone in primitive_cones:
     1058            ...       print fibration.fiber_component(primitive_cone)
     1059            2-d toric variety covered by 4 affine patches
     1060            2-d toric variety covered by 3 affine patches
     1061            2-d toric variety covered by 3 affine patches
     1062        """
     1063        if domain_cone.is_trivial():
     1064            return self.fiber()
     1065        embedding = SchemeMorphism_fan_fiber_toric_variety(self.domain(), self.fan_morphism(), domain_cone)
     1066        return embedding.domain()
     1067
     1068    @cached_method
     1069    def fiber_dimension(self, codomain_cone):
     1070        r"""
     1071        Return the dimension of the fiber over a particular torus
     1072        orbit in the base.
     1073       
     1074        EXAMPLES::
     1075
     1076            sage: P1xP1 = toric_varieties.P1xP1()
     1077            sage: P1 = toric_varieties.P1()
     1078            sage: f = P1xP1.hom(matrix([[1],[0]]), P1)
     1079            sage: f.fiber_dimension(P1.fan(0)[0])
     1080            1
     1081            sage: f.fiber_dimension(P1.fan(1)[0])
     1082            1
     1083            sage: f.fiber_dimension(P1.fan(1)[1])
     1084            1
     1085
     1086        Here is a more complicated example that is not a flat fibration::
     1087       
     1088            sage: A2_Z2 = toric_varieties.A2_Z2()
     1089            sage: O2_P1 = A2_Z2.resolve(new_rays=[(1,1)])
     1090            sage: blowup = O2_P1.hom(identity_matrix(2), A2_Z2)
     1091            sage: blowup.fiber_dimension(A2_Z2.fan(0)[0])
     1092            0
     1093            sage: blowup.fiber_dimension(A2_Z2.fan(1)[0])
     1094            0
     1095            sage: blowup.fiber_dimension(A2_Z2.fan(2)[0])
     1096            1
     1097           
     1098        This corresponds to the three different fibers::
     1099       
     1100            sage: blowup.fiber()
     1101            0-d affine toric variety
     1102            sage: blowup.fiber_component(Cone([(1,0)]))
     1103            0-d affine toric variety
     1104            sage: blowup.fiber_component(Cone([(1,1)]))
     1105            1-d toric variety covered by 2 affine patches
     1106        """
     1107        dim = []
     1108        fm = self.fan_morphism()
     1109        base_dim = codomain_cone.dim()
     1110        for c in fm.primitive_preimage_cones(codomain_cone):
     1111            dim.append(base_dim - c.dim())
     1112        return max(dim) + self.domain().dimension() - self.fan_morphism().matrix().rank()
     1113
     1114    def fiber_graph(self, codomain_cone):
     1115        r"""
     1116        Return the fiber over a given torus orbit in the codomain.
     1117
     1118        INPUT:
     1119
     1120        - ``codomain_cone`` -- a cone `\sigma` of the codomain,
     1121          specifying a torus orbit `O(\sigma)`.
     1122
     1123        OUTPUT:
     1124
     1125        A graph whose nodes are the irreducible components of the
     1126        fiber. If two irreducible components intersect, the
     1127        corresponding nodes of the graph are joined by an edge.
     1128
     1129        EXAMPLES::
     1130
     1131            sage: polytope = Polyhedron(
     1132            ...       [(-3,0,-1,-1),(-1,2,-1,-1),(0,-1,0,0),(0,0,0,1),(0,0,1,0),
     1133            ...        (0,1,0,0),(0,2,-1,-1),(1,0,0,0),(2,0,-1,-1)])
     1134            sage: coarse_fan = FaceFan(polytope.lattice_polytope())
     1135           
     1136            sage: P2 = toric_varieties.P2()
     1137            sage: proj34 = block_matrix(2,1,[zero_matrix(2,2), identity_matrix(2)])
     1138            sage: fm = FanMorphism(proj34, coarse_fan, P2.fan(), subdivide=True)
     1139            sage: fibration = ToricVariety(fm.domain_fan()).hom(fm, P2)
     1140
     1141            sage: fibration.fiber_graph( P2.fan(0)[0] )
     1142            Graph on 1 vertex
     1143            sage: for c1 in P2.fan(1):   
     1144            ...       fibration.fiber_graph(c1)   
     1145            Graph on 1 vertex
     1146            Graph on 1 vertex
     1147            Graph on 4 vertices
     1148
     1149            sage: fibration.fiber_graph(P2.fan(1)[2]).get_vertices()
     1150            {0: 2-d toric variety covered by 4 affine patches,
     1151             1: 2-d toric variety covered by 3 affine patches,
     1152             2: 2-d toric variety covered by 3 affine patches,
     1153             3: 2-d toric variety covered by 4 affine patches}
     1154
     1155            sage: fibration
     1156            Scheme morphism:
     1157              From: 4-d toric variety covered by 18 affine patches
     1158              To:   2-d CPR-Fano toric variety covered by 3 affine patches
     1159              Defn: Defined by sending Rational polyhedral fan in 4-d lattice N
     1160                    to Rational polyhedral fan in 2-d lattice N.
     1161        """
     1162        fm = self.fan_morphism()
     1163        prim = fm.primitive_preimage_cones(codomain_cone)
     1164        n = len(prim)
     1165       
     1166        def is_union_in_fan(self, c0, c1):
     1167            c = Cone(c0.rays() + c1.rays(), lattice=c0.lattice())
     1168            return fm.domain_fan().contains(c)
     1169        m = matrix(ZZ, n, n, lambda i,j:is_union_in_fan(self,prim[i], prim[j]))
     1170
     1171        for i in range(0,n):
     1172            m[i,i]=0
     1173        from sage.graphs.graph import Graph
     1174        graph = Graph(m, loops=False, multiedges=False)
     1175        for i in range(0,n):
     1176            graph.set_vertex(i, self.fiber_component(prim[i]))
     1177        return graph
     1178
     1179
     1180############################################################################
     1181# The embedding morphism of an orbit closure
     1182class SchemeMorphism_fan_fiber_toric_variety(SchemeMorphism):
     1183    """
     1184    The embedding of an orbit closure inside the fiber of a a toric
     1185    morphism.
     1186
     1187    Note that the embedding map of the fiber of a toric morphism is
     1188    itself not a toric morphism!
     1189
     1190    INPUT:
     1191
     1192    - ``toric_morphism`` -- a toric morphism. The toric morphism whose
     1193      fiber we are describing.
     1194
     1195    - ``defining_cone`` -- a cone of a fan. The primitive preimage
     1196      cones of the fan morphism definine the irreducible components of
     1197      the fiber of a toric morphism.
     1198
     1199    - ``check`` -- if ``True`` (default), the input will be checked for
     1200      correctness.
     1201
     1202    EXAMPLES::
     1203       
     1204        sage: polytope = Polyhedron(
     1205        ...       [(-3,0,-1,-1),(-1,2,-1,-1),(0,-1,0,0),(0,0,0,1),(0,0,1,0),
     1206        ...        (0,1,0,0),(0,2,-1,-1),(1,0,0,0),(2,0,-1,-1)])
     1207        sage: coarse_fan = FaceFan(polytope.lattice_polytope())
     1208        sage: P2 = toric_varieties.P2()
     1209        sage: proj24 = matrix([[0,0],[1,0],[0,0],[0,1]])
     1210        sage: fm = FanMorphism(proj24, coarse_fan, P2.fan(), subdivide=True)
     1211        sage: fibration = ToricVariety(fm.domain_fan()).hom(fm, P2)
     1212        sage: primitive_cones = fibration.fan_morphism().primitive_preimage_cones(P2.fan(1)[0])
     1213        sage: primitive_cone = primitive_cones[0]
     1214        sage: fiber_component = fibration.fiber_component(primitive_cone)
     1215        sage: fiber_component
     1216        2-d toric variety covered by 4 affine patches
     1217        sage: fiber_component.embedding_morphism()
     1218        Scheme morphism:
     1219          From: 2-d toric variety covered by 4 affine patches
     1220          To:   4-d toric variety covered by 23 affine patches
     1221          Defn: Defined by embedding the fiber irreducible component defined by the
     1222                primitive preimage cone 1-d cone of Rational polyhedral fan in 4-d lattice N.
     1223        sage: fiber_component.embedding_morphism().as_polynomial_map()
     1224        Scheme morphism:
     1225          From: 2-d toric variety covered by 4 affine patches
     1226          To:   4-d toric variety covered by 23 affine patches
     1227          Defn: Defined on coordinates by sending [z0 : z1 : z2 : z3] to
     1228                [1 : 1 : 1 : 1 : z1 : 0 : 1 : z0 : 1 : 1 : 1 : 1 : 1 : z3 : z2]
     1229        sage: type(fiber_component.embedding_morphism())
     1230        <class 'sage.schemes.toric.morphism.SchemeMorphism_fan_fiber_toric_variety'>
     1231    """
     1232   
     1233    def __init__(self, toric_variety, fan_morphism, defining_cone, check=True):
     1234        """
     1235        The Python constructor.
     1236
     1237        TESTS::
     1238
     1239            sage: polytope = Polyhedron(
     1240            ...       [(-3,0,-1,-1),(-1,2,-1,-1),(0,-1,0,0),(0,0,0,1),(0,0,1,0),
     1241            ...        (0,1,0,0),(0,2,-1,-1),(1,0,0,0),(2,0,-1,-1)])
     1242            sage: coarse_fan = FaceFan(polytope.lattice_polytope())
     1243            sage: P2 = toric_varieties.P2()
     1244            sage: proj24 = matrix([[0,0],[1,0],[0,0],[0,1]])
     1245            sage: fm = FanMorphism(proj24, coarse_fan, P2.fan(), subdivide=True)
     1246            sage: fibration = ToricVariety(fm.domain_fan()).hom(fm, P2)
     1247            sage: primitive_cone = Cone([(-1, 2, -1, 0)])
     1248            sage: fibration.fiber_component(primitive_cone)
     1249            2-d toric variety covered by 3 affine patches
     1250        """
     1251        if check and toric_variety.fan()!=fan_morphism.domain_fan():
     1252            raise ValueError('The total space toric variety must be the fan morphism codomain.')
     1253        self._fan_morphism = fan_morphism
     1254        self._defining_cone = fan_morphism.domain_fan().embed(defining_cone)
     1255        self._base_cone = fan_morphism.image_cone(defining_cone)
     1256        fiber = self._make_fiber()
     1257        fiber._embedding_morphism = self
     1258        parent = fiber.Hom(toric_variety)
     1259        SchemeMorphism.__init__(self, parent)
     1260
     1261    def _repr_defn(self):
     1262        """
     1263        Return a string representation of the definition of ``self``.
     1264
     1265        OUTPUT:
     1266
     1267        String.
     1268
     1269        EXAMPLES::
     1270
     1271            sage: P1xP1 = toric_varieties.P1xP1()
     1272            sage: P1 = toric_varieties.P1()
     1273            sage: fiber = P1xP1.hom(matrix([[1],[0]]), P1).fiber_component(Cone([(1,0)]))
     1274            sage: fiber.embedding_morphism()._repr_defn()
     1275            'Defined by embedding the fiber irreducible component defined by the primitive preimage cone 1-d cone of Rational polyhedral fan in 2-d lattice N.'
     1276        """
     1277        s  = 'Defined by embedding the fiber irreducible component defined by the primitive preimage cone '
     1278        s += str(self.defining_cone())
     1279        s += '.'
     1280        return s
     1281
     1282    def as_polynomial_map(self):
     1283        """
     1284        Express the embedding morphism via homogeneous polynomials.
     1285
     1286        OUTPUT:
     1287
     1288        A :class:`SchemeMorphism_polynomial_toric_variety`. Raises a
     1289        ``TypeError`` if the morphism cannot be written in terms of
     1290        homogeneous polynomials.
     1291       
     1292        EXAMPLES::
     1293
     1294            sage: polytope = Polyhedron(
     1295            ...       [(-3,0,-1,-1),(-1,2,-1,-1),(0,-1,0,0),(0,0,0,1),(0,0,1,0),
     1296            ...        (0,1,0,0),(0,2,-1,-1),(1,0,0,0),(2,0,-1,-1)])
     1297            sage: coarse_fan = FaceFan(polytope.lattice_polytope())
     1298            sage: P2 = toric_varieties.P2()
     1299            sage: proj24 = matrix([[0,0],[1,0],[0,0],[0,1]])
     1300            sage: fm = FanMorphism(proj24, coarse_fan, P2.fan(), subdivide=True)
     1301            sage: fibration = ToricVariety(fm.domain_fan()).hom(fm, P2)
     1302
     1303            sage: primitive_cone = Cone([(0, 1, 0, 0)])
     1304            sage: f = fibration.fiber_component(primitive_cone).embedding_morphism()
     1305            sage: f.as_polynomial_map()
     1306            Scheme morphism:
     1307              From: 2-d toric variety covered by 4 affine patches
     1308              To:   4-d toric variety covered by 23 affine patches
     1309              Defn: Defined on coordinates by sending [z0 : z1 : z2 : z3] to
     1310                    [1 : 1 : 1 : 1 : z1 : 0 : 1 : z0 : 1 : 1 : 1 : 1 : 1 : z3 : z2]
     1311
     1312            sage: primitive_cone = Cone([(-1, 2, -1, 0)])
     1313            sage: f = fibration.fiber_component(primitive_cone).embedding_morphism()
     1314            sage: f.as_polynomial_map()
     1315            Traceback (most recent call last):
     1316            ...
     1317            TypeError: The morphism cannot be written using homogeneous polynomials.
     1318        """
     1319        fiber = self.domain()
     1320        toric_variety = self.codomain()
     1321        R = fiber.coordinate_ring()
     1322        polys = [ R.one() ] * toric_variety.fan().nrays()
     1323        for i in self.defining_cone().ambient_ray_indices():
     1324            polys[i] = R.zero()
     1325        for ray, x in zip(fiber.fan().rays(), R.gens()):
     1326            try:
     1327                ray_index = self._ray_index_map[ray]
     1328            except KeyError:
     1329                raise TypeError('The morphism cannot be written using homogeneous polynomials.')
     1330            polys[ray_index] = x
     1331        return SchemeMorphism_polynomial_toric_variety(self.parent(), polys)
     1332
     1333    def _make_fiber(self):
     1334        """
     1335        Construct the fiber component as a toric variety.
     1336
     1337        OUTPUT:
     1338
     1339        The fiber component as a toric variety.
     1340
     1341        EXAMPLES::
     1342
     1343            sage: P1xP1 = toric_varieties.P1xP1()
     1344            sage: P1 = toric_varieties.P1()
     1345            sage: fiber = P1xP1.hom(matrix([[1],[0]]), P1).fiber_component(Cone([(1,0)]))
     1346            sage: f = fiber.embedding_morphism()
     1347            sage: f._ray_index_map  # indirect doctest
     1348            {N(-1): 3, N(1): 2}
     1349
     1350        TESTS::
     1351
     1352            sage: A2_Z2 = toric_varieties.A2_Z2()
     1353            sage: O2_P1 = A2_Z2.resolve(new_rays=[(1,1)])
     1354            sage: blowup = O2_P1.hom(identity_matrix(2), A2_Z2)
     1355            sage: blowup.fiber()
     1356            0-d affine toric variety
     1357            sage: blowup.fiber_component(Cone([(1,0)]))
     1358            0-d affine toric variety
     1359            sage: blowup.fiber_component(Cone([(1,1)]))
     1360            1-d toric variety covered by 2 affine patches
     1361        """
     1362        fm = self._fan_morphism
     1363        defining_cone = self._defining_cone
     1364        base_cone = self._base_cone
     1365
     1366        ker = fm.kernel().basis()
     1367        base_cone_preimg = [ fm.matrix().solve_left(r) for r in base_cone.rays() ]
     1368        L = fm.domain_fan().lattice().submodule(ker+base_cone_preimg).saturation()
     1369
     1370        cone_L = Cone([L.coordinates(r) for r in defining_cone.rays()])
     1371        L_quotient = cone_L.sublattice_quotient()
     1372       
     1373        def projection(ray):
     1374            ray_L = L.coordinates(ray)
     1375            return vector(ZZ, L_quotient(ray_L))
     1376
     1377        cones = []
     1378        star_rays = set()
     1379        for cone in fm.relative_star_generators(defining_cone):
     1380            star_rays.update(cone.rays())
     1381            projected_rays = [ projection(r) for r in cone.rays() ]
     1382            cones.append(Cone(projected_rays))
     1383        fiber_fan = Fan(cones)
     1384
     1385        ray_index_map = dict()
     1386        for ray in star_rays:
     1387            ray_index = fm.domain_fan().rays().index(ray)
     1388            projected_ray = fiber_fan.lattice()(projection(ray))
     1389            if projected_ray.is_zero():
     1390                assert ray in defining_cone.rays()
     1391                continue
     1392            projected_ray.set_immutable()
     1393            ray_index_map[projected_ray] = ray_index
     1394        self._ray_index_map = ray_index_map
     1395
     1396        from sage.schemes.toric.variety import ToricVariety
     1397        return ToricVariety(fiber_fan)
     1398
     1399    def defining_cone(self):
     1400        r"""
     1401        Return the cone corresponding to the fiber torus orbit.
     1402       
     1403        OUTPUT:
     1404       
     1405        A cone of the fan of the total space of the toric fibration.
     1406        """
     1407        return self._defining_cone
     1408   
     1409    def base_cone(self):
     1410        r"""
     1411        Return the base cone `\sigma`.
     1412       
     1413        The fiber is constant over the base orbit closure `V(\sigma)`.
     1414
     1415        OUTPUT:
     1416
     1417        A cone of the base of the toric fibration.
     1418        """
     1419        return self._base_cone
    8771420    def is_birational(self):
    8781421        r"""
    8791422        Check if ``self`` is birational.