Ticket #9972: trac_9972_add_cone_embedding.patch
File trac_9972_add_cone_embedding.patch, 11.7 KB (added by , 10 years ago) |
---|
-
sage/geometry/cone.py
# HG changeset patch # User Andrey Novoseltsev <novoselt@gmail.com> # Date 1287093111 21600 # Node ID 241bda86abc36028e5ad52efaa80e771944a1854 # Parent 52545114f01fa96880097a9e04ddd7297827ac7f Trac 9972: Add embedding of cones and keep ray order for fans generated by a single cone. diff -r 52545114f01f -r 241bda86abc3 sage/geometry/cone.py
a b 1549 1549 self._dual._dual = self 1550 1550 return self._dual 1551 1551 1552 def embed(self, cone): 1553 r""" 1554 Return the cone equivalent to the given one, but sitting in ``self`` as 1555 a face. 1556 1557 You may need to use this method before calling methods of ``cone`` that 1558 depend on the ambient structure, such as 1559 :meth:`~sage.geometry.cone.ConvexRationalPolyhedralCone.ambient_ray_indices` 1560 or 1561 :meth:`~sage.geometry.cone.ConvexRationalPolyhedralCone.facet_of`. The 1562 cone returned by this method will have ``self`` as ambient. If ``cone`` 1563 does not represent a valid cone of ``self``, ``ValueError`` exception 1564 is raised. 1565 1566 .. NOTE:: 1567 1568 This method is very quick if ``self`` is already the ambient 1569 structure of ``cone``, so you can use without extra checks and 1570 performance hit even if ``cone`` is likely to sit in ``self`` but 1571 in principle may not. 1572 1573 INPUT: 1574 1575 - ``cone`` -- a :class:`cone 1576 <sage.geometry.cone.ConvexRationalPolyhedralCone>`. 1577 1578 OUTPUT: 1579 1580 - a :class:`cone <sage.geometry.cone.ConvexRationalPolyhedralCone>`, 1581 equivalent to ``cone`` but sitting inside ``self``. 1582 1583 EXAMPLES: 1584 1585 Let's take a 3-d cone on 4 rays:: 1586 1587 sage: c = Cone([(1,0,1), (0,1,1), (-1,0,1), (0,-1,1)]) 1588 1589 Then any ray generates a 1-d face of this cone, but if you construct 1590 such a face directly, it will not "sit" inside the cone:: 1591 1592 sage: ray = Cone([(0,-1,1)]) 1593 sage: ray 1594 1-d cone in 3-d lattice N 1595 sage: ray.ambient_ray_indices() 1596 (0,) 1597 sage: ray.adjacent() 1598 () 1599 sage: ray.ambient() 1600 1-d cone in 3-d lattice N 1601 1602 If we want to operate with this ray as a face of the cone, we need to 1603 embed it first:: 1604 1605 sage: e_ray = c.embed(ray) 1606 sage: e_ray 1607 1-d face of 3-d cone in 3-d lattice N 1608 sage: e_ray.rays() 1609 (N(0, -1, 1),) 1610 sage: e_ray is ray 1611 False 1612 sage: e_ray.is_equivalent(ray) 1613 True 1614 sage: e_ray.ambient_ray_indices() 1615 (3,) 1616 sage: e_ray.adjacent() 1617 (1-d face of 3-d cone in 3-d lattice N, 1618 1-d face of 3-d cone in 3-d lattice N) 1619 sage: e_ray.ambient() 1620 3-d cone in 3-d lattice N 1621 1622 Not every cone can be embedded into a fixed ambient cone:: 1623 1624 sage: c.embed(Cone([(0,0,1)])) 1625 Traceback (most recent call last): 1626 ... 1627 ValueError: 1-d cone in 3-d lattice N is not a face 1628 of 3-d cone in 3-d lattice N! 1629 sage: c.embed(Cone([(1,0,1), (-1,0,1)])) 1630 Traceback (most recent call last): 1631 ... 1632 ValueError: 2-d cone in 3-d lattice N is not a face 1633 of 3-d cone in 3-d lattice N! 1634 """ 1635 assert is_Cone(cone) 1636 if cone.ambient() is self: 1637 return cone 1638 if self.is_strictly_convex(): 1639 rays = self.rays() 1640 try: 1641 ray_indices = tuple(sorted(rays.index(ray) 1642 for ray in cone.rays())) 1643 for face in self.faces(cone.dim()): 1644 if face.ambient_ray_indices() == ray_indices: 1645 return face 1646 except ValueError: 1647 pass 1648 else: 1649 # We cannot use the trick with indices since rays are not unique. 1650 for face in self.faces(cone.dim()): 1651 if cone.is_equivalent(face): 1652 return face 1653 # If we are here, then either ValueError was raised or we went through 1654 # all faces and didn't find the matching one. 1655 raise ValueError("%s is not a face of %s!" % (cone, self)) 1656 1552 1657 def face_lattice(self): 1553 1658 r""" 1554 1659 Return the face lattice of ``self``. … … 2063 2168 sage: cone1.is_equivalent(cone2) 2064 2169 True 2065 2170 """ 2171 if self is other: 2172 return True 2173 # TODO: Next check is pointless if cones and fans are made to be unique 2174 if self.ambient() is other.ambient() and self.is_strictly_convex(): 2175 return self.ambient_ray_indices() == other.ambient_ray_indices() 2066 2176 if self.lattice() != other.lattice(): 2067 2177 return False 2068 2178 if self.ray_set() == other.ray_set(): -
sage/geometry/fan.py
diff -r 52545114f01f -r 241bda86abc3 sage/geometry/fan.py
a b 425 425 (), (), rays[0].parent() if rays else lattice) 426 426 if is_Cone(cones[0]): 427 427 # Construct the fan from Cone objects 428 if lattice is None: 429 lattice = cones[0].lattice() 428 430 if check: 429 431 for cone in cones: 430 432 if not cone.is_strictly_convex(): 431 433 raise ValueError( 432 434 "cones of a fan must be strictly convex!") 435 if cone.lattice() != lattice: 436 raise ValueError("all cones of a fan must be in %s, but " 437 "%s is not!" % (lattice, cone)) 438 # Optimization for fans generated by a single cone 439 if len(cones) == 1: 440 cone = cones[0] 441 return RationalPolyhedralFan((tuple(range(cone.nrays())), ), 442 cone.rays(), lattice, 443 is_complete=lattice.dimension() == 0) 433 444 ray_set = set([]) 434 445 for cone in cones: 435 446 ray_set.update(cone.rays()) … … 1239 1250 sage: new_fan = fan._subdivide_palp(new_rays, True) 1240 1251 R:1/1 C:2 T:...(ms) T/new:...(ms) T/all:...(ms) 1241 1252 sage: new_fan.ray_matrix() 1253 [1 0 1] 1242 1254 [0 1 1] 1243 [1 0 1]1244 1255 sage: for cone in new_fan: print cone.ambient_ray_indices() 1256 (1, 2) 1245 1257 (0, 2) 1246 (1, 2)1247 1258 1248 1259 We make sure that this function constructs cones with ordered ambient 1249 1260 ray indices (see Trac 9812):: … … 1251 1262 sage: C = Cone([(1,0,0), (0,1,0), (1,0,1), (0,1,1)]) 1252 1263 sage: F = Fan([C]).make_simplicial() 1253 1264 sage: [cone.ambient_ray_indices() for cone in F] 1254 [(0, 1, 3), (0, 1, 2)]1265 [(0, 2, 3), (0, 1, 3)] 1255 1266 """ 1256 1267 dim = self.lattice_dim() 1257 1268 for cone in self: … … 1676 1687 data = data[0] 1677 1688 return self._contains(data) 1678 1689 1690 def embed(self, cone): 1691 r""" 1692 Return the cone equivalent to the given one, but sitting in ``self``. 1693 1694 You may need to use this method before calling methods of ``cone`` that 1695 depend on the ambient structure, such as 1696 :meth:`~sage.geometry.cone.ConvexRationalPolyhedralCone.ambient_ray_indices` 1697 or 1698 :meth:`~sage.geometry.cone.ConvexRationalPolyhedralCone.facet_of`. The 1699 cone returned by this method will have ``self`` as ambient. If ``cone`` 1700 does not represent a valid cone of ``self``, ``ValueError`` exception 1701 is raised. 1702 1703 .. NOTE:: 1704 1705 This method is very quick if ``self`` is already the ambient 1706 structure of ``cone``, so you can use without extra checks and 1707 performance hit even if ``cone`` is likely to sit in ``self`` but 1708 in principle may not. 1709 1710 INPUT: 1711 1712 - ``cone`` -- a :class:`cone 1713 <sage.geometry.cone.ConvexRationalPolyhedralCone>`. 1714 1715 OUTPUT: 1716 1717 - a :class:`cone of fan <Cone_of_fan>`, equivalent to ``cone`` but 1718 sitting inside ``self``. 1719 1720 EXAMPLES: 1721 1722 Let's take a 3-d fan generated by a cone on 4 rays:: 1723 1724 sage: f = Fan([Cone([(1,0,1), (0,1,1), (-1,0,1), (0,-1,1)])]) 1725 1726 Then any ray generates a 1-d cone of this fan, but if you construct 1727 such a cone directly, it will not "sit" inside the fan:: 1728 1729 sage: ray = Cone([(0,-1,1)]) 1730 sage: ray 1731 1-d cone in 3-d lattice N 1732 sage: ray.ambient_ray_indices() 1733 (0,) 1734 sage: ray.adjacent() 1735 () 1736 sage: ray.ambient() 1737 1-d cone in 3-d lattice N 1738 1739 If we want to operate with this ray as a part of the fan, we need to 1740 embed it first:: 1741 1742 sage: e_ray = f.embed(ray) 1743 sage: e_ray 1744 1-d cone of Rational polyhedral fan in 3-d lattice N 1745 sage: e_ray.rays() 1746 (N(0, -1, 1),) 1747 sage: e_ray is ray 1748 False 1749 sage: e_ray.is_equivalent(ray) 1750 True 1751 sage: e_ray.ambient_ray_indices() 1752 (3,) 1753 sage: e_ray.adjacent() 1754 (1-d cone of Rational polyhedral fan in 3-d lattice N, 1755 1-d cone of Rational polyhedral fan in 3-d lattice N) 1756 sage: e_ray.ambient() 1757 Rational polyhedral fan in 3-d lattice N 1758 1759 Not every cone can be embedded into a fixed fan:: 1760 1761 sage: f.embed(Cone([(0,0,1)])) 1762 Traceback (most recent call last): 1763 ... 1764 ValueError: 1-d cone in 3-d lattice N does not belong 1765 to Rational polyhedral fan in 3-d lattice N! 1766 sage: f.embed(Cone([(1,0,1), (-1,0,1)])) 1767 Traceback (most recent call last): 1768 ... 1769 ValueError: 2-d cone in 3-d lattice N does not belong 1770 to Rational polyhedral fan in 3-d lattice N! 1771 """ 1772 assert is_Cone(cone) 1773 if cone.ambient() is self: 1774 return cone 1775 rays = self.rays() 1776 try: 1777 # Compute ray indices 1778 ray_indices = [rays.index(ray) for ray in cone.rays()] 1779 # Get the smallest cone containing them 1780 result = self.cone_containing(*ray_indices) 1781 # It should be equivalent to the original one 1782 if not result.is_equivalent(cone): 1783 raise ValueError 1784 except ValueError: 1785 raise ValueError("%s does not belong to %s!" % (cone, self)) 1786 return result 1787 1679 1788 def Gale_transform(self): 1680 1789 r""" 1681 1790 Return the Gale transform of ``self``. -
sage/schemes/generic/toric_variety.py
diff -r 52545114f01f -r 241bda86abc3 sage/schemes/generic/toric_variety.py
a b 1545 1545 sage: TV_res.is_smooth() 1546 1546 True 1547 1547 sage: TV_res.fan().ray_matrix() 1548 [ -11 0]1548 [ 1 -1 0] 1549 1549 [ 1 1 1] 1550 1550 sage: [cone.ambient_ray_indices() for cone in TV_res.fan()] 1551 [( 1, 2), (0, 2)]1551 [(0, 2), (1, 2)] 1552 1552 1553 1553 Now let's "automatically" partially resolve a more complicated fan:: 1554 1554