297 | | |
| 297 | |
| 298 | def __mul__(self, right): |
| 299 | """ |
| 300 | Return the composition of ``self`` and ``right``. |
| 301 | |
| 302 | INPUT: |
| 303 | |
| 304 | - ``right`` -- a :class:`FanMorphism` whose :meth:`codomain_fan` can be |
| 305 | mapped to :meth:`domain_fan` of ``self`` via identity map of lattices. |
| 306 | |
| 307 | OUTPUT: |
| 308 | |
| 309 | - a :class:`FanMorphism`. |
| 310 | |
| 311 | EXAMPLES:: |
| 312 | |
| 313 | sage: A2 = toric_varieties.A2() |
| 314 | sage: P3 = toric_varieties.P(3) |
| 315 | sage: m = matrix([(2,0,0), (1,1,0)]) |
| 316 | sage: phi = A2.hom(m, P3).fan_morphism() |
| 317 | sage: phi |
| 318 | Fan morphism defined by the matrix |
| 319 | [2 0 0] |
| 320 | [1 1 0] |
| 321 | Domain fan: Rational polyhedral fan in 2-d lattice N |
| 322 | Codomain fan: Rational polyhedral fan in 3-d lattice N |
| 323 | sage: prod(phi.factor()) # indirect test |
| 324 | Fan morphism defined by the matrix |
| 325 | [2 0 0] |
| 326 | [1 1 0] |
| 327 | Domain fan: Rational polyhedral fan in 2-d lattice N |
| 328 | Codomain fan: Rational polyhedral fan in 3-d lattice N |
| 329 | """ |
| 330 | if not isinstance(right, FanMorphism): |
| 331 | raise TypeError( |
| 332 | "fan morphisms should be composed with fan morphisms") |
| 333 | # We don't need it, we just check compatibility of fans: |
| 334 | FanMorphism(identity_matrix(self.domain().dimension()), |
| 335 | right.codomain_fan(), self.domain_fan()) |
| 336 | m = right.matrix() * self.matrix() |
| 337 | return FanMorphism(m, right.domain_fan(), self.codomain_fan()) |
| 338 | |
1027 | 1071 | sage: [zeta.index(cone) for cone in flatten(Sigma_p.cones())] |
1028 | 1072 | [+Infinity, None, None, None, None, None, None, None, None, None, |
1029 | 1073 | 4, 4, None, 4, None, None, 2, None, 4, None, 4, 1, 1, 1, 1, 1, 1] |
| 1096 | def is_birational(self): |
| 1097 | r""" |
| 1098 | Check if ``self`` is birational. |
| 1099 | |
| 1100 | OUTPUT: |
| 1101 | |
| 1102 | - ``True`` if ``self`` is birational, ``False`` otherwise. |
| 1103 | |
| 1104 | For fan morphisms this check is equivalent to ``self.index() == 1`` and |
| 1105 | means that the corresponding map between toric varieties is birational. |
| 1106 | |
| 1107 | EXAMPLES:: |
| 1108 | |
| 1109 | sage: Sigma = toric_varieties.dP8().fan() |
| 1110 | sage: Sigma_p = toric_varieties.P1().fan() |
| 1111 | sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) |
| 1112 | sage: psi = FanMorphism(matrix([[2], [-2]]), Sigma, Sigma_p) |
| 1113 | sage: xi = FanMorphism(matrix([[1, 0]]), Sigma_p, Sigma) |
| 1114 | sage: phi.index(), psi.index(), xi.index() |
| 1115 | (1, 2, +Infinity) |
| 1116 | sage: phi.is_birational(), psi.is_birational(), xi.is_birational() |
| 1117 | (True, False, False) |
| 1118 | """ |
| 1119 | return self.index() == 1 |
| 1120 | |
1627 | | - a :class:`fan morphism <FanMorphism>`. |
| 1695 | - a triple of :class:`FanMorphism` `(\phi_i, \phi_b, \phi_s)`, such that |
| 1696 | `\phi_s` is surjective, `\phi_b` is birational, `\phi_i` is injective, |
| 1697 | and ``self`` is equal to `\phi_i \circ \phi_b \circ \phi_s`. |
| 1698 | |
| 1699 | Intermediate fans live in the saturation of the image of ``self`` |
| 1700 | as a map between lattices and are the image of the :meth:`domain_fan` |
| 1701 | and the restriction of the :meth:`codomain_fan`, i.e. if ``self`` maps |
| 1702 | `\Sigma \to \Sigma'`, then we have factorization into |
1631 | | By the *image fan* of a fan morphism we mean the fan generated by |
1632 | | the intersections of cones of the codomain fan with the image |
1633 | | vector space of ``self``. The lattice of this fan is the saturation |
1634 | | of the image of ``self``. |
1635 | | |
| 1716 | * `\Sigma_s` is the finest fan with the smallest support that is |
| 1717 | compatible with ``self``: any fan morphism from `\Sigma` given by |
| 1718 | the same map of lattices as ``self`` factors through `\Sigma_s`. |
| 1719 | |
| 1720 | * `\Sigma_i` is the coarsest fan of the largest support that is |
| 1721 | compatible with ``self``: any fan morphism into `\Sigma'` given by |
| 1722 | the same map of lattices as ``self`` factors though `\Sigma_i`. |
| 1723 | |
1638 | | We embed a projective line "diagonally" into the product of two lines:: |
| 1726 | We map an affine plane into a projective 3-space in such a way, that it |
| 1727 | becomes "a double cover of a chart of the blow up of one of the |
| 1728 | coordinate planes":: |
| 1729 | |
| 1730 | sage: A2 = toric_varieties.A2() |
| 1731 | sage: P3 = toric_varieties.P(3) |
| 1732 | sage: m = matrix([(2,0,0), (1,1,0)]) |
| 1733 | sage: phi = A2.hom(m, P3) |
| 1734 | sage: phi.as_polynomial_map() |
| 1735 | Scheme morphism: |
| 1736 | From: 2-d affine toric variety |
| 1737 | To: 3-d CPR-Fano toric variety covered by 4 affine patches |
| 1738 | Defn: Defined on coordinates by sending [x : y] to |
| 1739 | [x^2*y : y : 1 : 1] |
| 1746 | [2 0 0] |
| 1747 | [1 1 0] |
| 1748 | Domain fan: Rational polyhedral fan in 2-d lattice N |
| 1749 | Codomain fan: Rational polyhedral fan in 3-d lattice N |
| 1750 | sage: phi.is_surjective(), phi.is_birational(), phi.is_injective() |
| 1751 | (False, False, False) |
| 1752 | sage: phi_i, phi_b, phi_s = phi.factor() |
| 1753 | sage: phi_s.is_surjective(), phi_b.is_birational(), phi_i.is_injective() |
| 1754 | (True, True, True) |
| 1755 | sage: prod(phi.factor()) == phi |
| 1756 | True |
| 1757 | |
| 1758 | Double cover (surjective):: |
| 1759 | |
| 1760 | sage: A2.fan().rays() |
| 1761 | N(1, 0), |
| 1762 | N(0, 1) |
| 1763 | in 2-d lattice N |
| 1764 | sage: phi_s |
| 1765 | Fan morphism defined by the matrix |
| 1766 | [2 0] |
1647 | | Domain fan: Rational polyhedral fan in 1-d lattice N |
1648 | | Codomain fan: Rational polyhedral fan in 2-d lattice N |
| 1768 | Domain fan: Rational polyhedral fan in 2-d lattice N |
| 1769 | Codomain fan: Rational polyhedral fan in Sublattice <N(1, 0, 0), N(0, 1, 0)> |
| 1770 | sage: phi_s.codomain_fan().rays() |
| 1771 | N(1, 0, 0), |
| 1772 | N(1, 1, 0) |
| 1773 | in Sublattice <N(1, 0, 0), N(0, 1, 0)> |
| 1774 | |
| 1775 | Blowup chart (birational):: |
| 1776 | |
| 1777 | sage: phi_b |
| 1778 | Fan morphism defined by the matrix |
| 1779 | [1 0] |
| 1780 | [0 1] |
| 1781 | Domain fan: Rational polyhedral fan in Sublattice <N(1, 0, 0), N(0, 1, 0)> |
| 1782 | Codomain fan: Rational polyhedral fan in Sublattice <N(1, 0, 0), N(0, 1, 0)> |
| 1783 | sage: phi_b.codomain_fan().rays() |
| 1784 | N( 1, 0, 0), |
| 1785 | N( 0, 1, 0), |
| 1786 | N(-1, -1, 0) |
| 1787 | in Sublattice <N(1, 0, 0), N(0, 1, 0)> |
1664 | | sage: psi.codomain().gens() |
1665 | | (N(1, 1),) |
1666 | | sage: psi.codomain_fan().rays() |
1667 | | N( 1, 1), |
1668 | | N(-1, -1) |
1669 | | in Sublattice <N(1, 1)> |
1670 | | |
1671 | | Restriction to image returns exactly the same map if the corresponding |
1672 | | map of vector spaces is surjective, e.g. in the case of double |
1673 | | restriction:: |
1674 | | |
1675 | | sage: psi.restrict_to_image() is psi |
| 1806 | sage: phi_s.matrix() * phi_b.matrix() * phi_i.matrix() == m |
| 1807 | True |
| 1808 | |
| 1809 | sage: phi.domain_fan() is phi_s.domain_fan() |
| 1810 | True |
| 1811 | sage: phi_s.codomain_fan() is phi_b.domain_fan() |
| 1812 | True |
| 1813 | sage: phi_b.codomain_fan() is phi_i.domain_fan() |
| 1814 | True |
| 1815 | sage: phi_i.codomain_fan() is phi.codomain_fan() |
1685 | | Sigma = Fan(cones=discard_faces(L_cone.intersection(cone) |
1686 | | for cone in self.codomain_fan()), |
1687 | | lattice=L, check=False) |
1688 | | return FanMorphism(m, self.domain_fan(), Sigma) |
| 1825 | Sigma_i = Fan(cones=(L_cone.intersection(cone) for cone in Sigma_prime), |
| 1826 | lattice=L, discard_faces=True, check=False) |
| 1827 | phi_b = FanMorphism(identity_matrix(d), phi_s.codomain_fan(), Sigma_i, |
| 1828 | check=False) |
| 1829 | phi_i = FanMorphism(L.basis_matrix(), Sigma_i, Sigma_prime, check=False) |
| 1830 | return (phi_i, phi_b, phi_s) |