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 self._dual._dual = self return self._dual def embed(self, cone): r""" Return the cone equivalent to the given one, but sitting in ``self`` as a face. You may need to use this method before calling methods of ``cone`` that depend on the ambient structure, such as :meth:`~sage.geometry.cone.ConvexRationalPolyhedralCone.ambient_ray_indices` or :meth:`~sage.geometry.cone.ConvexRationalPolyhedralCone.facet_of`. The cone returned by this method will have ``self`` as ambient. If ``cone`` does not represent a valid cone of ``self``, ``ValueError`` exception is raised. .. NOTE:: This method is very quick if ``self`` is already the ambient structure of ``cone``, so you can use without extra checks and performance hit even if ``cone`` is likely to sit in ``self`` but in principle may not. INPUT: - ``cone`` -- a :class:`cone `. OUTPUT: - a :class:`cone `, equivalent to ``cone`` but sitting inside ``self``. EXAMPLES: Let's take a 3-d cone on 4 rays:: sage: c = Cone([(1,0,1), (0,1,1), (-1,0,1), (0,-1,1)]) Then any ray generates a 1-d face of this cone, but if you construct such a face directly, it will not "sit" inside the cone:: sage: ray = Cone([(0,-1,1)]) sage: ray 1-d cone in 3-d lattice N sage: ray.ambient_ray_indices() (0,) sage: ray.adjacent() () sage: ray.ambient() 1-d cone in 3-d lattice N If we want to operate with this ray as a face of the cone, we need to embed it first:: sage: e_ray = c.embed(ray) sage: e_ray 1-d face of 3-d cone in 3-d lattice N sage: e_ray.rays() (N(0, -1, 1),) sage: e_ray is ray False sage: e_ray.is_equivalent(ray) True sage: e_ray.ambient_ray_indices() (3,) sage: e_ray.adjacent() (1-d face of 3-d cone in 3-d lattice N, 1-d face of 3-d cone in 3-d lattice N) sage: e_ray.ambient() 3-d cone in 3-d lattice N Not every cone can be embedded into a fixed ambient cone:: sage: c.embed(Cone([(0,0,1)])) Traceback (most recent call last): ... ValueError: 1-d cone in 3-d lattice N is not a face of 3-d cone in 3-d lattice N! sage: c.embed(Cone([(1,0,1), (-1,0,1)])) Traceback (most recent call last): ... ValueError: 2-d cone in 3-d lattice N is not a face of 3-d cone in 3-d lattice N! """ assert is_Cone(cone) if cone.ambient() is self: return cone if self.is_strictly_convex(): rays = self.rays() try: ray_indices = tuple(sorted(rays.index(ray) for ray in cone.rays())) for face in self.faces(cone.dim()): if face.ambient_ray_indices() == ray_indices: return face except ValueError: pass else: # We cannot use the trick with indices since rays are not unique. for face in self.faces(cone.dim()): if cone.is_equivalent(face): return face # If we are here, then either ValueError was raised or we went through # all faces and didn't find the matching one. raise ValueError("%s is not a face of %s!" % (cone, self)) def face_lattice(self): r""" Return the face lattice of ``self``. sage: cone1.is_equivalent(cone2) True """ if self is other: return True # TODO: Next check is pointless if cones and fans are made to be unique if self.ambient() is other.ambient() and self.is_strictly_convex(): return self.ambient_ray_indices() == other.ambient_ray_indices() if self.lattice() != other.lattice(): return False if self.ray_set() == other.ray_set():
• sage/geometry/fan.py

diff -r 52545114f01f -r 241bda86abc3 sage/geometry/fan.py
 a (), (), rays.parent() if rays else lattice) if is_Cone(cones): # Construct the fan from Cone objects if lattice is None: lattice = cones.lattice() if check: for cone in cones: if not cone.is_strictly_convex(): raise ValueError( "cones of a fan must be strictly convex!") if cone.lattice() != lattice: raise ValueError("all cones of a fan must be in %s, but " "%s is not!" % (lattice, cone)) # Optimization for fans generated by a single cone if len(cones) == 1: cone = cones return RationalPolyhedralFan((tuple(range(cone.nrays())), ), cone.rays(), lattice, is_complete=lattice.dimension() == 0) ray_set = set([]) for cone in cones: ray_set.update(cone.rays()) sage: new_fan = fan._subdivide_palp(new_rays, True) R:1/1  C:2  T:...(ms)  T/new:...(ms)  T/all:...(ms) sage: new_fan.ray_matrix() [1 0 1] [0 1 1] [1 0 1] sage: for cone in new_fan: print cone.ambient_ray_indices() (1, 2) (0, 2) (1, 2) We make sure that this function constructs cones with ordered ambient ray indices (see Trac 9812):: sage: C = Cone([(1,0,0), (0,1,0), (1,0,1), (0,1,1)]) sage: F = Fan([C]).make_simplicial() sage: [cone.ambient_ray_indices() for cone in F] [(0, 1, 3), (0, 1, 2)] [(0, 2, 3), (0, 1, 3)] """ dim = self.lattice_dim() for cone in self: data = data return self._contains(data) def embed(self, cone): r""" Return the cone equivalent to the given one, but sitting in ``self``. You may need to use this method before calling methods of ``cone`` that depend on the ambient structure, such as :meth:`~sage.geometry.cone.ConvexRationalPolyhedralCone.ambient_ray_indices` or :meth:`~sage.geometry.cone.ConvexRationalPolyhedralCone.facet_of`. The cone returned by this method will have ``self`` as ambient. If ``cone`` does not represent a valid cone of ``self``, ``ValueError`` exception is raised. .. NOTE:: This method is very quick if ``self`` is already the ambient structure of ``cone``, so you can use without extra checks and performance hit even if ``cone`` is likely to sit in ``self`` but in principle may not. INPUT: - ``cone`` -- a :class:`cone `. OUTPUT: - a :class:`cone of fan `, equivalent to ``cone`` but sitting inside ``self``. EXAMPLES: Let's take a 3-d fan generated by a cone on 4 rays:: sage: f = Fan([Cone([(1,0,1), (0,1,1), (-1,0,1), (0,-1,1)])]) Then any ray generates a 1-d cone of this fan, but if you construct such a cone directly, it will not "sit" inside the fan:: sage: ray = Cone([(0,-1,1)]) sage: ray 1-d cone in 3-d lattice N sage: ray.ambient_ray_indices() (0,) sage: ray.adjacent() () sage: ray.ambient() 1-d cone in 3-d lattice N If we want to operate with this ray as a part of the fan, we need to embed it first:: sage: e_ray = f.embed(ray) sage: e_ray 1-d cone of Rational polyhedral fan in 3-d lattice N sage: e_ray.rays() (N(0, -1, 1),) sage: e_ray is ray False sage: e_ray.is_equivalent(ray) True sage: e_ray.ambient_ray_indices() (3,) sage: e_ray.adjacent() (1-d cone of Rational polyhedral fan in 3-d lattice N, 1-d cone of Rational polyhedral fan in 3-d lattice N) sage: e_ray.ambient() Rational polyhedral fan in 3-d lattice N Not every cone can be embedded into a fixed fan:: sage: f.embed(Cone([(0,0,1)])) Traceback (most recent call last): ... ValueError: 1-d cone in 3-d lattice N does not belong to Rational polyhedral fan in 3-d lattice N! sage: f.embed(Cone([(1,0,1), (-1,0,1)])) Traceback (most recent call last): ... ValueError: 2-d cone in 3-d lattice N does not belong to Rational polyhedral fan in 3-d lattice N! """ assert is_Cone(cone) if cone.ambient() is self: return cone rays = self.rays() try: # Compute ray indices ray_indices = [rays.index(ray) for ray in cone.rays()] # Get the smallest cone containing them result = self.cone_containing(*ray_indices) # It should be equivalent to the original one if not result.is_equivalent(cone): raise ValueError except ValueError: raise ValueError("%s does not belong to %s!" % (cone, self)) return result def Gale_transform(self): r""" Return the Gale transform of ``self``.
• sage/schemes/generic/toric_variety.py

diff -r 52545114f01f -r 241bda86abc3 sage/schemes/generic/toric_variety.py
 a sage: TV_res.is_smooth() True sage: TV_res.fan().ray_matrix() [-1  1  0] [ 1 -1  0] [ 1  1  1] sage: [cone.ambient_ray_indices() for cone in TV_res.fan()] [(1, 2), (0, 2)] [(0, 2), (1, 2)] Now let's "automatically" partially resolve a more complicated fan::