Ticket #9972: trac_9972_add_cone_embedding.patch

File trac_9972_add_cone_embedding.patch, 11.7 KB (added by novoselt, 9 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  
    15491549            self._dual._dual = self
    15501550        return self._dual       
    15511551   
     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           
    15521657    def face_lattice(self):
    15531658        r"""
    15541659        Return the face lattice of ``self``.
     
    20632168            sage: cone1.is_equivalent(cone2)
    20642169            True
    20652170        """
     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()
    20662176        if self.lattice() != other.lattice():
    20672177            return False
    20682178        if self.ray_set() == other.ray_set():
  • sage/geometry/fan.py

    diff -r 52545114f01f -r 241bda86abc3 sage/geometry/fan.py
    a b  
    425425                                (), (), rays[0].parent() if rays else lattice)
    426426    if is_Cone(cones[0]):
    427427        # Construct the fan from Cone objects
     428        if lattice is None:
     429            lattice = cones[0].lattice()
    428430        if check:
    429431            for cone in cones:
    430432                if not cone.is_strictly_convex():
    431433                    raise ValueError(
    432434                                    "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)
    433444        ray_set = set([])
    434445        for cone in cones:
    435446            ray_set.update(cone.rays())
     
    12391250            sage: new_fan = fan._subdivide_palp(new_rays, True)
    12401251            R:1/1  C:2  T:...(ms)  T/new:...(ms)  T/all:...(ms)
    12411252            sage: new_fan.ray_matrix()
     1253            [1 0 1]
    12421254            [0 1 1]
    1243             [1 0 1]
    12441255            sage: for cone in new_fan: print cone.ambient_ray_indices()
     1256            (1, 2)
    12451257            (0, 2)
    1246             (1, 2)
    12471258           
    12481259        We make sure that this function constructs cones with ordered ambient
    12491260        ray indices (see Trac 9812)::
     
    12511262            sage: C = Cone([(1,0,0), (0,1,0), (1,0,1), (0,1,1)])
    12521263            sage: F = Fan([C]).make_simplicial()
    12531264            sage: [cone.ambient_ray_indices() for cone in F]
    1254             [(0, 1, 3), (0, 1, 2)]       
     1265            [(0, 2, 3), (0, 1, 3)]       
    12551266        """
    12561267        dim = self.lattice_dim()
    12571268        for cone in self:
     
    16761687           data = data[0]
    16771688        return self._contains(data)
    16781689
     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           
    16791788    def Gale_transform(self):
    16801789        r"""
    16811790        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  
    15451545            sage: TV_res.is_smooth()
    15461546            True
    15471547            sage: TV_res.fan().ray_matrix()
    1548             [-1  1  0]
     1548            [ 1 -1  0]
    15491549            [ 1  1  1]
    15501550            sage: [cone.ambient_ray_indices() for cone in TV_res.fan()]
    1551             [(1, 2), (0, 2)]
     1551            [(0, 2), (1, 2)]
    15521552
    15531553        Now let's "automatically" partially resolve a more complicated fan::
    15541554