diff --git a/src/sage/geometry/abc.pyx b/src/sage/geometry/abc.pyx index 4db85b7ace8..f3aee46d324 100644 --- a/src/sage/geometry/abc.pyx +++ b/src/sage/geometry/abc.pyx @@ -13,13 +13,13 @@ class LatticePolytope: EXAMPLES:: sage: import sage.geometry.abc - sage: P = LatticePolytope([(1,2,3), (4,5,6)]) # optional - sage.geometry.polyhedron - sage: isinstance(P, sage.geometry.abc.LatticePolytope) # optional - sage.geometry.polyhedron + sage: P = LatticePolytope([(1,2,3), (4,5,6)]) # needs sage.geometry.polyhedron + sage: isinstance(P, sage.geometry.abc.LatticePolytope) # needs sage.geometry.polyhedron True By design, there is a unique direct subclass:: - sage: sage.geometry.abc.LatticePolytope.__subclasses__() # optional - sage.geometry.polyhedron + sage: sage.geometry.abc.LatticePolytope.__subclasses__() # needs sage.geometry.polyhedron [] sage: len(sage.geometry.abc.Polyhedron.__subclasses__()) <= 1 @@ -39,13 +39,13 @@ class ConvexRationalPolyhedralCone: EXAMPLES:: sage: import sage.geometry.abc - sage: C = cones.nonnegative_orthant(2) # optional - sage.geometry.polyhedron - sage: isinstance(C, sage.geometry.abc.ConvexRationalPolyhedralCone) # optional - sage.geometry.polyhedron + sage: C = cones.nonnegative_orthant(2) # needs sage.geometry.polyhedron + sage: isinstance(C, sage.geometry.abc.ConvexRationalPolyhedralCone) # needs sage.geometry.polyhedron True By design, there is a unique direct subclass:: - sage: sage.geometry.abc.ConvexRationalPolyhedralCone.__subclasses__() # optional - sage.geometry.polyhedron + sage: sage.geometry.abc.ConvexRationalPolyhedralCone.__subclasses__() # needs sage.geometry.polyhedron [] sage: len(sage.geometry.abc.Polyhedron.__subclasses__()) <= 1 @@ -65,13 +65,13 @@ class Polyhedron: EXAMPLES:: sage: import sage.geometry.abc - sage: P = polytopes.cube() # optional - sage.geometry.polyhedron - sage: isinstance(P, sage.geometry.abc.Polyhedron) # optional - sage.geometry.polyhedron + sage: P = polytopes.cube() # needs sage.geometry.polyhedron + sage: isinstance(P, sage.geometry.abc.Polyhedron) # needs sage.geometry.polyhedron True By design, there is a unique direct subclass:: - sage: sage.geometry.abc.Polyhedron.__subclasses__() # optional - sage.geometry.polyhedron + sage: sage.geometry.abc.Polyhedron.__subclasses__() # needs sage.geometry.polyhedron [] sage: len(sage.geometry.abc.Polyhedron.__subclasses__()) <= 1 diff --git a/src/sage/geometry/cone.py b/src/sage/geometry/cone.py index d37a444a564..058de82afc2 100644 --- a/src/sage/geometry/cone.py +++ b/src/sage/geometry/cone.py @@ -129,31 +129,33 @@ You can work with subcones that form faces of other cones:: - sage: face = four_rays.faces(dim=2)[0] # optional - sage.graphs - sage: face # optional - sage.graphs + sage: # needs sage.graphs + sage: face = four_rays.faces(dim=2)[0] + sage: face 2-d face of 3-d cone in 3-d lattice N - sage: face.rays() # optional - sage.graphs + sage: face.rays() N(-1, -1, 1), N(-1, 1, 1) in 3-d lattice N - sage: face.ambient_ray_indices() # optional - sage.graphs + sage: face.ambient_ray_indices() (2, 3) - sage: four_rays.rays(face.ambient_ray_indices()) # optional - sage.graphs + sage: four_rays.rays(face.ambient_ray_indices()) N(-1, -1, 1), N(-1, 1, 1) in 3-d lattice N If you need to know inclusion relations between faces, you can use :: - sage: L = four_rays.face_lattice() # optional - sage.graphs - sage: [len(s) for s in L.level_sets()] # optional - sage.graphs + sage: # needs sage.graphs + sage: L = four_rays.face_lattice() + sage: [len(s) for s in L.level_sets()] [1, 4, 4, 1] - sage: face = L.level_sets()[2][0] # optional - sage.graphs - sage: face.rays() # optional - sage.graphs + sage: face = L.level_sets()[2][0] + sage: face.rays() N(1, 1, 1), N(1, -1, 1) in 3-d lattice N - sage: L.hasse_diagram().neighbors_in(face) # optional - sage.graphs + sage: L.hasse_diagram().neighbors_in(face) [1-d face of 3-d cone in 3-d lattice N, 1-d face of 3-d cone in 3-d lattice N] @@ -572,9 +574,9 @@ def _ambient_space_point(body, data): (1, 1/3) sage: _ambient_space_point(c, vector(QQ,[1,1/3])) (1, 1/3) - sage: _ambient_space_point(c, [1/2, 1/sqrt(3)]) # optional - sage.symbolic sage.rings.number_field + sage: _ambient_space_point(c, [1/2, 1/sqrt(3)]) # needs sage.rings.number_field sage.symbolic (1/2, 0.5773502691896258?) - sage: _ambient_space_point(c, vector(AA, [1/2, 1/sqrt(3)])) # optional - sage.symbolic sage.rings.number_field + sage: _ambient_space_point(c, vector(AA, [1/2, 1/sqrt(3)])) # needs sage.rings.number_field sage.symbolic (1/2, 0.5773502691896258?) sage: _ambient_space_point(c, [1,1,3]) Traceback (most recent call last): @@ -592,9 +594,9 @@ def _ambient_space_point(body, data): sage: from sage.geometry.cone import _ambient_space_point sage: c = Cone([(1,0), (0,1)]) - sage: _ambient_space_point(c, [1, pi]) # optional - sage.symbolic sage.rings.number_field + sage: _ambient_space_point(c, [1, pi]) # needs sage.rings.number_field sage.symbolic (1.00000000000000, 3.14159265358979) - sage: _ambient_space_point(c, vector(SR,[1, pi])) # optional - sage.symbolic sage.rings.number_field + sage: _ambient_space_point(c, vector(SR,[1, pi])) # needs sage.rings.number_field sage.symbolic (1.00000000000000, 3.14159265358979) """ @@ -1005,7 +1007,7 @@ def ambient_vector_space(self, base_field=None): sage: c = Cone([(1,0)]) sage: c.ambient_vector_space() Vector space of dimension 2 over Rational Field - sage: c.ambient_vector_space(AA) # optional - sage.rings.number_field + sage: c.ambient_vector_space(AA) # needs sage.rings.number_field Vector space of dimension 2 over Algebraic Real Field """ return self.lattice().vector_space(base_field=base_field) @@ -1098,7 +1100,7 @@ def plot(self, **options): EXAMPLES:: sage: quadrant = Cone([(1,0), (0,1)]) - sage: quadrant.plot() # optional - sage.plot + sage: quadrant.plot() # needs sage.plot Graphics object consisting of 9 graphics primitives """ tp = ToricPlotter(options, self.lattice().degree(), self.rays()) @@ -1601,7 +1603,7 @@ def __getstate__(self): TESTS:: sage: C = Cone([(1,0)]) - sage: C.face_lattice() # optional - sage.graphs sage.combinat + sage: C.face_lattice() # needs sage.combinat sage.graphs Finite lattice containing 2 elements with distinguished linear extension sage: C._test_pickling() sage: C2 = loads(dumps(C)); C2 @@ -1674,17 +1676,17 @@ def _contains(self, point, region='whole cone'): We can test vectors with irrational components:: sage: c = Cone([(1,0), (0,1)]) - sage: c._contains((1, sqrt(2))) # optional - sage.symbolic + sage: c._contains((1, sqrt(2))) # needs sage.symbolic True - sage: c._contains(vector(SR, [1, pi])) # optional - sage.symbolic + sage: c._contains(vector(SR, [1, pi])) # needs sage.symbolic True Ensure that complex vectors are not contained in a real cone:: sage: c = Cone([(1,0), (0,1)]) - sage: c._contains((1,I)) # optional - sage.symbolic + sage: c._contains((1,I)) # needs sage.symbolic False - sage: c._contains(vector(QQbar, [1,I])) # optional - sage.rings.number_field sage.symbolic + sage: c._contains(vector(QQbar, [1,I])) # needs sage.rings.number_field sage.symbolic False And we refuse to coerce elements of another lattice into ours:: @@ -1971,7 +1973,7 @@ def _latex_(self): sage: quadrant = Cone([(1,0), (0,1)]) sage: quadrant._latex_() '\\sigma^{2}' - sage: quadrant.facets()[0]._latex_() # optional - sage.graphs + sage: quadrant.facets()[0]._latex_() # needs sage.graphs '\\sigma^{1} \\subset \\sigma^{2}' """ if self.ambient() is self: @@ -1995,7 +1997,7 @@ def _repr_(self): '2-d cone in 2-d lattice N' sage: quadrant 2-d cone in 2-d lattice N - sage: quadrant.facets()[0] # optional - sage.graphs + sage: quadrant.facets()[0] # needs sage.graphs 1-d face of 2-d cone in 2-d lattice N """ result = "%d-d" % self.dim() @@ -2051,7 +2053,7 @@ def _sort_faces(self, faces): sage: octant = Cone(identity_matrix(3).columns()) sage: # indirect doctest - sage: for i, face in enumerate(octant.faces(1)): # optional - sage.graphs + sage: for i, face in enumerate(octant.faces(1)): # needs sage.graphs ....: if face.ray(0) != octant.ray(i): ....: print("Wrong order!") """ @@ -2095,13 +2097,14 @@ def adjacent(self): EXAMPLES:: + sage: # needs sage.graphs sage: octant = Cone([(1,0,0), (0,1,0), (0,0,1)]) - sage: octant.adjacent() # optional - sage.graphs + sage: octant.adjacent() () - sage: one_face = octant.faces(1)[0] # optional - sage.graphs - sage: len(one_face.adjacent()) # optional - sage.graphs + sage: one_face = octant.faces(1)[0] + sage: len(one_face.adjacent()) 2 - sage: one_face.adjacent()[1] # optional - sage.graphs + sage: one_face.adjacent()[1] 1-d face of 3-d cone in 3-d lattice N Things are a little bit subtle with fans, as we illustrate below. @@ -2111,7 +2114,7 @@ def adjacent(self): sage: fan = Fan(cones=[(0,1), (1,2)], ....: rays=[(1,0), (0,1), (-1,0)]) sage: cone = fan.generating_cone(0) - sage: len(cone.adjacent()) # optional - sage.graphs + sage: len(cone.adjacent()) # needs sage.graphs 1 The second generating cone is adjacent to this one. Now we create the @@ -2120,7 +2123,7 @@ def adjacent(self): sage: fan = Fan(cones=[(0,1), (1,2)], ....: rays=[(1,0,0), (0,1,0), (-1,0,0)]) sage: cone = fan.generating_cone(0) - sage: len(cone.adjacent()) # optional - sage.graphs + sage: len(cone.adjacent()) # needs sage.graphs 1 The result is as before, since we still have:: @@ -2133,7 +2136,7 @@ def adjacent(self): sage: fan = Fan(cones=[(0,1), (1,2), (3,)], ....: rays=[(1,0,0), (0,1,0), (-1,0,0), (0,0,1)]) sage: cone = fan.generating_cone(0) - sage: len(cone.adjacent()) # optional - sage.graphs + sage: len(cone.adjacent()) # needs sage.graphs 0 Since now ``cone`` has smaller dimension than ``fan``, it and its @@ -2176,12 +2179,14 @@ def ambient(self): 3-d cone in 3-d lattice N sage: cone.ambient() is cone True - sage: face = cone.faces(1)[0] # optional - sage.graphs - sage: face # optional - sage.graphs + + sage: # needs sage.graphs + sage: face = cone.faces(1)[0] + sage: face 1-d face of 3-d cone in 3-d lattice N - sage: face.ambient() # optional - sage.graphs + sage: face.ambient() 3-d cone in 3-d lattice N - sage: face.ambient() is cone # optional - sage.graphs + sage: face.ambient() is cone True """ return self._ambient @@ -2199,7 +2204,7 @@ def ambient_ray_indices(self): sage: quadrant = Cone([(1,0), (0,1)]) sage: quadrant.ambient_ray_indices() (0, 1) - sage: quadrant.facets()[1].ambient_ray_indices() # optional - sage.graphs + sage: quadrant.facets()[1].ambient_ray_indices() # needs sage.graphs (1,) """ return self._ambient_ray_indices @@ -2238,9 +2243,9 @@ def contains(self, *args): False sage: c.contains(1) False - sage: c.contains(1/2, sqrt(3)) # optional - sage.symbolic + sage: c.contains(1/2, sqrt(3)) # needs sage.symbolic True - sage: c.contains(-1/2, sqrt(3)) # optional - sage.symbolic + sage: c.contains(-1/2, sqrt(3)) # needs sage.symbolic False """ point = flatten(args) @@ -2369,7 +2374,7 @@ def embed(self, cone): 1-d cone in 3-d lattice N sage: ray.ambient_ray_indices() (0,) - sage: ray.adjacent() # optional - sage.graphs + sage: ray.adjacent() # needs sage.graphs () sage: ray.ambient() 1-d cone in 3-d lattice N @@ -2377,22 +2382,23 @@ def embed(self, cone): 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) # optional - sage.graphs - sage: e_ray # optional - sage.graphs + sage: # needs sage.graphs + 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() # optional - sage.graphs + sage: e_ray.rays() N(0, -1, 1) in 3-d lattice N - sage: e_ray is ray # optional - sage.graphs + sage: e_ray is ray False - sage: e_ray.is_equivalent(ray) # optional - sage.graphs + sage: e_ray.is_equivalent(ray) True - sage: e_ray.ambient_ray_indices() # optional - sage.graphs + sage: e_ray.ambient_ray_indices() (3,) - sage: e_ray.adjacent() # optional - sage.graphs + 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() # optional - sage.graphs + sage: e_ray.ambient() 3-d cone in 3-d lattice N Not every cone can be embedded into a fixed ambient cone:: @@ -2402,7 +2408,7 @@ def embed(self, cone): ... 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)])) # optional - sage.graphs + sage: c.embed(Cone([(1,0,1), (-1,0,1)])) # needs sage.graphs Traceback (most recent call last): ... ValueError: 2-d cone in 3-d lattice N is not a face @@ -2447,13 +2453,13 @@ def face_lattice(self): Let's take a look at the face lattice of the first quadrant:: sage: quadrant = Cone([(1,0), (0,1)]) - sage: L = quadrant.face_lattice() # optional - sage.graphs sage.combinat - sage: L # optional - sage.graphs sage.combinat + sage: L = quadrant.face_lattice() # needs sage.combinat sage.graphs + sage: L # needs sage.combinat sage.graphs Finite lattice containing 4 elements with distinguished linear extension To see all faces arranged by dimension, you can do this:: - sage: for level in L.level_sets(): print(level) # optional - sage.graphs sage.combinat + sage: for level in L.level_sets(): print(level) # needs sage.combinat sage.graphs [0-d face of 2-d cone in 2-d lattice N] [1-d face of 2-d cone in 2-d lattice N, 1-d face of 2-d cone in 2-d lattice N] @@ -2461,15 +2467,15 @@ def face_lattice(self): For a particular face you can look at its actual rays... :: - sage: face = L.level_sets()[1][0] # optional - sage.graphs sage.combinat - sage: face.rays() # optional - sage.graphs sage.combinat + sage: face = L.level_sets()[1][0] # needs sage.combinat sage.graphs + sage: face.rays() # needs sage.combinat sage.graphs N(1, 0) in 2-d lattice N ... or you can see the index of the ray of the original cone that corresponds to the above one:: - sage: face.ambient_ray_indices() # optional - sage.graphs sage.combinat + sage: face.ambient_ray_indices() # needs sage.combinat sage.graphs (0,) sage: quadrant.ray(0) N(1, 0) @@ -2477,56 +2483,58 @@ def face_lattice(self): An alternative to extracting faces from the face lattice is to use :meth:`faces` method:: - sage: face is quadrant.faces(dim=1)[0] # optional - sage.graphs sage.combinat + sage: face is quadrant.faces(dim=1)[0] # needs sage.combinat sage.graphs True The advantage of working with the face lattice directly is that you can (relatively easily) get faces that are related to the given one:: - sage: face = L.level_sets()[1][0] # optional - sage.graphs sage.combinat - sage: D = L.hasse_diagram() # optional - sage.graphs sage.combinat - sage: sorted(D.neighbors(face)) # optional - sage.graphs sage.combinat + sage: face = L.level_sets()[1][0] # needs sage.combinat sage.graphs + sage: D = L.hasse_diagram() # needs sage.combinat sage.graphs + sage: sorted(D.neighbors(face)) # needs sage.combinat sage.graphs [0-d face of 2-d cone in 2-d lattice N, 2-d cone in 2-d lattice N] However, you can achieve some of this functionality using :meth:`facets`, :meth:`facet_of`, and :meth:`adjacent` methods:: - sage: face = quadrant.faces(1)[0] # optional - sage.graphs - sage: face # optional - sage.graphs + sage: # needs sage.graphs + sage: face = quadrant.faces(1)[0] + sage: face 1-d face of 2-d cone in 2-d lattice N - sage: face.rays() # optional - sage.graphs + sage: face.rays() N(1, 0) in 2-d lattice N - sage: face.facets() # optional - sage.graphs + sage: face.facets() (0-d face of 2-d cone in 2-d lattice N,) - sage: face.facet_of() # optional - sage.graphs + sage: face.facet_of() (2-d cone in 2-d lattice N,) - sage: face.adjacent() # optional - sage.graphs + sage: face.adjacent() (1-d face of 2-d cone in 2-d lattice N,) - sage: face.adjacent()[0].rays() # optional - sage.graphs + sage: face.adjacent()[0].rays() N(0, 1) in 2-d lattice N Note that if ``cone`` is a face of ``supercone``, then the face lattice of ``cone`` consists of (appropriate) faces of ``supercone``:: + sage: # needs sage.combinat sage.graphs sage: supercone = Cone([(1,2,3,4), (5,6,7,8), ....: (1,2,4,8), (1,3,9,7)]) - sage: supercone.face_lattice() # optional - sage.graphs sage.combinat + sage: supercone.face_lattice() Finite lattice containing 16 elements with distinguished linear extension - sage: supercone.face_lattice().top() # optional - sage.graphs sage.combinat + sage: supercone.face_lattice().top() 4-d cone in 4-d lattice N - sage: cone = supercone.facets()[0] # optional - sage.graphs sage.combinat - sage: cone # optional - sage.graphs sage.combinat + sage: cone = supercone.facets()[0] + sage: cone 3-d face of 4-d cone in 4-d lattice N - sage: cone.face_lattice() # optional - sage.graphs sage.combinat + sage: cone.face_lattice() Finite poset containing 8 elements with distinguished linear extension - sage: cone.face_lattice().bottom() # optional - sage.graphs sage.combinat + sage: cone.face_lattice().bottom() 0-d face of 4-d cone in 4-d lattice N - sage: cone.face_lattice().top() # optional - sage.graphs sage.combinat + sage: cone.face_lattice().top() 3-d face of 4-d cone in 4-d lattice N - sage: cone.face_lattice().top() == cone # optional - sage.graphs sage.combinat + sage: cone.face_lattice().top() == cone True TESTS:: @@ -2542,19 +2550,19 @@ def face_lattice(self): to have non identical face lattices, even if the faces themselves are equal (see :trac:`10998`):: - sage: C1.face_lattice() is C2.face_lattice() # optional - sage.graphs sage.combinat + sage: C1.face_lattice() is C2.face_lattice() # needs sage.combinat sage.graphs False - sage: C1.facets()[0] # optional - sage.graphs + sage: C1.facets()[0] # needs sage.graphs 0-d face of 1-d cone in 2-d lattice N - sage: C2.facets()[0] # optional - sage.graphs + sage: C2.facets()[0] # needs sage.graphs 0-d face of 1-d cone in 2-d lattice N - sage: C1.facets()[0].ambient() is C1 # optional - sage.graphs + sage: C1.facets()[0].ambient() is C1 # needs sage.graphs True - sage: C2.facets()[0].ambient() is C1 # optional - sage.graphs + sage: C2.facets()[0].ambient() is C1 # needs sage.graphs False - sage: C2.facets()[0].ambient() is C2 # optional - sage.graphs + sage: C2.facets()[0].ambient() is C2 # needs sage.graphs True """ if "_face_lattice" not in self.__dict__: @@ -2680,50 +2688,51 @@ def faces(self, dim=None, codim=None): Let's take a look at the faces of the first quadrant:: sage: quadrant = Cone([(1,0), (0,1)]) - sage: quadrant.faces() # optional - sage.graphs + sage: quadrant.faces() # needs sage.graphs ((0-d face of 2-d cone in 2-d lattice N,), (1-d face of 2-d cone in 2-d lattice N, 1-d face of 2-d cone in 2-d lattice N), (2-d cone in 2-d lattice N,)) - sage: quadrant.faces(dim=1) # optional - sage.graphs + sage: quadrant.faces(dim=1) # needs sage.graphs (1-d face of 2-d cone in 2-d lattice N, 1-d face of 2-d cone in 2-d lattice N) - sage: face = quadrant.faces(dim=1)[0] # optional - sage.graphs + sage: face = quadrant.faces(dim=1)[0] # needs sage.graphs Now you can look at the actual rays of this face... :: - sage: face.rays() # optional - sage.graphs + sage: face.rays() # needs sage.graphs N(1, 0) in 2-d lattice N ... or you can see indices of the rays of the original cone that correspond to the above ray:: - sage: face.ambient_ray_indices() # optional - sage.graphs + sage: face.ambient_ray_indices() # needs sage.graphs (0,) sage: quadrant.ray(0) N(1, 0) Note that it is OK to ask for faces of too small or high dimension:: - sage: quadrant.faces(-1) # optional - sage.graphs + sage: quadrant.faces(-1) # needs sage.graphs () - sage: quadrant.faces(3) # optional - sage.graphs + sage: quadrant.faces(3) # needs sage.graphs () In the case of non-strictly convex cones even faces of small non-negative dimension may be missing:: + sage: # needs sage.graphs sage: halfplane = Cone([(1,0), (0,1), (-1,0)]) - sage: halfplane.faces(0) # optional - sage.graphs + sage: halfplane.faces(0) () - sage: halfplane.faces() # optional - sage.graphs + sage: halfplane.faces() ((1-d face of 2-d cone in 2-d lattice N,), (2-d cone in 2-d lattice N,)) - sage: plane = Cone([(1,0), (0,1), (-1,-1)]) # optional - sage.graphs - sage: plane.faces(1) # optional - sage.graphs + sage: plane = Cone([(1,0), (0,1), (-1,-1)]) + sage: plane.faces(1) () - sage: plane.faces() # optional - sage.graphs + sage: plane.faces() ((2-d cone in 2-d lattice N,),) TESTS: @@ -2732,7 +2741,7 @@ def faces(self, dim=None, codim=None): dimension of the ambient space work as expected (see :trac:`9188`):: sage: c = Cone([(1,1,1,3),(1,-1,1,3),(-1,-1,1,3)]) - sage: c.faces() # optional - sage.graphs + sage: c.faces() # needs sage.graphs ((0-d face of 3-d cone in 4-d lattice N,), (1-d face of 3-d cone in 4-d lattice N, 1-d face of 3-d cone in 4-d lattice N, @@ -2745,16 +2754,17 @@ def faces(self, dim=None, codim=None): We also ensure that a call to this function does not break :meth:`facets` method (see :trac:`9780`):: - sage: cone = toric_varieties.dP8().fan().generating_cone(0); cone # optional - palp + sage: # needs palp sage.graphs + sage: cone = toric_varieties.dP8().fan().generating_cone(0); cone 2-d cone of Rational polyhedral fan in 2-d lattice N - sage: for f in cone.facets(): print(f.rays()) # optional - palp sage.graphs + sage: for f in cone.facets(): print(f.rays()) N(1, 1) in 2-d lattice N N(0, 1) in 2-d lattice N - sage: len(cone.faces()) # optional - palp sage.graphs + sage: len(cone.faces()) 3 - sage: for f in cone.facets(): print(f.rays()) # optional - palp sage.graphs + sage: for f in cone.facets(): print(f.rays()) N(1, 1) in 2-d lattice N N(0, 1) @@ -2900,26 +2910,27 @@ def facet_of(self): EXAMPLES:: + sage: # needs sage.graphs sage: octant = Cone([(1,0,0), (0,1,0), (0,0,1)]) - sage: octant.facet_of() # optional - sage.graphs + sage: octant.facet_of() () - sage: one_face = octant.faces(1)[0] # optional - sage.graphs - sage: len(one_face.facet_of()) # optional - sage.graphs + sage: one_face = octant.faces(1)[0] + sage: len(one_face.facet_of()) 2 - sage: one_face.facet_of()[1] # optional - sage.graphs + sage: one_face.facet_of()[1] 2-d face of 3-d cone in 3-d lattice N While fan is the top element of its own cone lattice, which is a variant of a face lattice, we do not refer to cones as its facets:: - sage: fan = Fan([octant]) - sage: fan.generating_cone(0).facet_of() # optional - sage.graphs + sage: fan = Fan([octant]) # needs sage.graphs + sage: fan.generating_cone(0).facet_of() # needs sage.graphs () Subcones of generating cones work as before:: - sage: one_cone = fan(1)[0] # optional - sage.graphs - sage: len(one_cone.facet_of()) # optional - sage.graphs + sage: one_cone = fan(1)[0] # needs sage.graphs + sage: len(one_cone.facet_of()) # needs sage.graphs 2 """ L = self._ambient._face_lattice_function() @@ -2938,7 +2949,7 @@ def facets(self): EXAMPLES:: sage: quadrant = Cone([(1,0), (0,1)]) - sage: quadrant.facets() # optional - sage.graphs + sage: quadrant.facets() # needs sage.graphs (1-d face of 2-d cone in 2-d lattice N, 1-d face of 2-d cone in 2-d lattice N) """ @@ -3257,19 +3268,19 @@ def is_isomorphic(self, other): We check that :trac:`18613` is fixed:: sage: K = cones.trivial(0) - sage: K.is_isomorphic(K) # optional - sage.graphs + sage: K.is_isomorphic(K) # needs sage.graphs True sage: K = cones.trivial(1) - sage: K.is_isomorphic(K) # optional - sage.graphs + sage: K.is_isomorphic(K) # needs sage.graphs True sage: K = cones.trivial(2) - sage: K.is_isomorphic(K) # optional - sage.graphs + sage: K.is_isomorphic(K) True A random (strictly convex) cone is isomorphic to itself:: sage: K = random_cone(max_ambient_dim=6, strictly_convex=True) - sage: K.is_isomorphic(K) # optional - sage.graphs + sage: K.is_isomorphic(K) # needs sage.graphs True """ if self.is_strictly_convex() and other.is_strictly_convex(): @@ -3484,7 +3495,7 @@ def plot(self, **options): EXAMPLES:: sage: quadrant = Cone([(1,0), (0,1)]) - sage: quadrant.plot() # optional - sage.plot + sage: quadrant.plot() # needs sage.plot Graphics object consisting of 9 graphics primitives """ # What to do with 3-d cones in 5-d? Use some projection method? @@ -3754,7 +3765,7 @@ def solid_restriction(self): the original:: sage: K = random_cone(max_ambient_dim=6) - sage: len(K.solid_restriction().facets()) == len(K.facets()) # optional - sage.graphs + sage: len(K.solid_restriction().facets()) == len(K.facets()) # needs sage.graphs True """ if self.is_solid(): @@ -3915,17 +3926,18 @@ def sublattice_quotient(self, *args, **kwds): EXAMPLES:: + sage: # needs sage.graphs sage: C2_Z2 = Cone([(1,0), (1,2)]) # C^2/Z_2 - sage: c1, c2 = C2_Z2.facets() # optional - sage.graphs - sage: c2.sublattice_quotient() # optional - sage.graphs + sage: c1, c2 = C2_Z2.facets() + sage: c2.sublattice_quotient() 1-d lattice, quotient of 2-d lattice N by Sublattice sage: N = C2_Z2.lattice() sage: n = N(1,1) - sage: n_bar = c2.sublattice_quotient(n); n_bar # optional - sage.graphs + sage: n_bar = c2.sublattice_quotient(n); n_bar N[1, 1] - sage: n_bar.lift() # optional - sage.graphs + sage: n_bar.lift() N(1, 1) - sage: vector(n_bar) # optional - sage.graphs + sage: vector(n_bar) (-1) """ if "_sublattice_quotient" not in self.__dict__: @@ -3968,10 +3980,10 @@ def sublattice_complement(self, *args, **kwds): EXAMPLES:: sage: C2_Z2 = Cone([(1,0), (1,2)]) # C^2/Z_2 - sage: c1, c2 = C2_Z2.facets() # optional - sage.graphs - sage: c2.sublattice() # optional - sage.graphs + sage: c1, c2 = C2_Z2.facets() # needs sage.graphs + sage: c2.sublattice() # needs sage.graphs Sublattice - sage: c2.sublattice_complement() # optional - sage.graphs + sage: c2.sublattice_complement() # needs sage.graphs Sublattice A more complicated example:: @@ -4197,30 +4209,32 @@ def relative_orthogonal_quotient(self, supercone): EXAMPLES:: + sage: # needs sage.graphs sage: rho = Cone([(1,1,1,3), (1,-1,1,3), (-1,-1,1,3), (-1,1,1,3)]) sage: rho.orthogonal_sublattice() Sublattice - sage: sigma = rho.facets()[1] # optional - sage.graphs - sage: sigma.orthogonal_sublattice() # optional - sage.graphs + sage: sigma = rho.facets()[1] + sage: sigma.orthogonal_sublattice() Sublattice - sage: sigma.is_face_of(rho) # optional - sage.graphs + sage: sigma.is_face_of(rho) True - sage: Q = sigma.relative_orthogonal_quotient(rho); Q # optional - sage.graphs + sage: Q = sigma.relative_orthogonal_quotient(rho); Q 1-d lattice, quotient of Sublattice by Sublattice - sage: Q.gens() # optional - sage.graphs + sage: Q.gens() (M[0, 1, 1, 0],) Different codimension:: + sage: # needs sage.graphs sage: rho = Cone([[1,-1,1,3],[-1,-1,1,3]]) - sage: sigma = rho.facets()[0] # optional - sage.graphs - sage: sigma.orthogonal_sublattice() # optional - sage.graphs + sage: sigma = rho.facets()[0] + sage: sigma.orthogonal_sublattice() Sublattice - sage: rho.orthogonal_sublattice() # optional - sage.graphs + sage: rho.orthogonal_sublattice() Sublattice - sage: sigma.relative_orthogonal_quotient(rho).gens() # optional - sage.graphs + sage: sigma.relative_orthogonal_quotient(rho).gens() (M[-1, 0, -2, 1],) Sign choice in the codimension one case:: @@ -5733,19 +5747,20 @@ def positive_operators_gens(self, K2=None): The positive operators on a permuted cone can be obtained by conjugation:: + sage: # needs sage.groups sage: K = random_cone(max_ambient_dim=3) sage: L = ToricLattice(K.lattice_dim()**2) - sage: p = SymmetricGroup(K.lattice_dim()).random_element().matrix() # optional - sage.groups - sage: pK = Cone((p*k for k in K), K.lattice(), check=False) # optional - sage.groups - sage: pi_gens = pK.positive_operators_gens() # optional - sage.groups - sage: actual = Cone((g.list() for g in pi_gens), # optional - sage.groups + sage: p = SymmetricGroup(K.lattice_dim()).random_element().matrix() + sage: pK = Cone((p*k for k in K), K.lattice(), check=False) + sage: pi_gens = pK.positive_operators_gens() + sage: actual = Cone((g.list() for g in pi_gens), ....: lattice=L, ....: check=False) sage: pi_gens = K.positive_operators_gens() - sage: expected = Cone(((p*g*p.inverse()).list() for g in pi_gens), # optional - sage.groups + sage: expected = Cone(((p*g*p.inverse()).list() for g in pi_gens), ....: lattice=L, ....: check=False) - sage: actual.is_equivalent(expected) # optional - sage.groups + sage: actual.is_equivalent(expected) True An operator is positive from one cone to another if and only if @@ -6056,19 +6071,20 @@ def cross_positive_operators_gens(self): The cross-positive operators of a permuted cone can be obtained by conjugation:: + sage: # needs sage.groups sage: K = random_cone(max_ambient_dim=3) sage: L = ToricLattice(K.lattice_dim()**2) - sage: p = SymmetricGroup(K.lattice_dim()).random_element().matrix() # optional - sage.groups - sage: pK = Cone((p*k for k in K), K.lattice(), check=False) # optional - sage.groups - sage: cp_gens = pK.cross_positive_operators_gens() # optional - sage.groups - sage: actual = Cone((g.list() for g in cp_gens), # optional - sage.groups + sage: p = SymmetricGroup(K.lattice_dim()).random_element().matrix() + sage: pK = Cone((p*k for k in K), K.lattice(), check=False) + sage: cp_gens = pK.cross_positive_operators_gens() + sage: actual = Cone((g.list() for g in cp_gens), ....: lattice=L, ....: check=False) sage: cp_gens = K.cross_positive_operators_gens() - sage: expected = Cone(((p*g*p.inverse()).list() for g in cp_gens), # optional - sage.groups + sage: expected = Cone(((p*g*p.inverse()).list() for g in cp_gens), ....: lattice=L, ....: check=False) - sage: actual.is_equivalent(expected) # optional - sage.groups + sage: actual.is_equivalent(expected) True An operator is cross-positive on a cone if and only if its diff --git a/src/sage/geometry/cone_catalog.py b/src/sage/geometry/cone_catalog.py index 185391d261a..d6898d40087 100644 --- a/src/sage/geometry/cone_catalog.py +++ b/src/sage/geometry/cone_catalog.py @@ -374,8 +374,8 @@ def rearrangement(p, ambient_dim=None, lattice=None): sage: ambient_dim = ZZ.random_element(2,10).abs() sage: p = ZZ.random_element(1, ambient_dim) sage: K = cones.rearrangement(p, ambient_dim) - sage: P = SymmetricGroup(ambient_dim).random_element().matrix() # optional - sage.groups - sage: all(K.contains(P*r) for r in K) # optional - sage.groups + sage: P = SymmetricGroup(ambient_dim).random_element().matrix() # needs sage.groups + sage: all(K.contains(P*r) for r in K) # needs sage.groups True The smallest ``p`` components of every element of the rearrangement @@ -527,13 +527,14 @@ def schur(ambient_dim=None, lattice=None): generators of the Schur cone and the nonnegative orthant in dimension five is `\left(3/4\right)\pi`:: + sage: # needs sage.rings.number_fields sage: P = cones.schur(5) sage: Q = cones.nonnegative_orthant(5) - sage: G = ( g.change_ring(QQbar).normalized() for g in P ) # optional - sage.rings.number_fields - sage: H = ( h.change_ring(QQbar).normalized() for h in Q ) # optional - sage.rings.number_fields - sage: actual = max(arccos(u.inner_product(v)) for u in G for v in H) # optional - sage.rings.number_fields - sage: expected = 3*pi/4 # optional - sage.rings.number_fields - sage: abs(actual - expected).n() < 1e-12 # optional - sage.rings.number_fields + sage: G = ( g.change_ring(QQbar).normalized() for g in P ) + sage: H = ( h.change_ring(QQbar).normalized() for h in Q ) + sage: actual = max(arccos(u.inner_product(v)) for u in G for v in H) + sage: expected = 3*pi/4 + sage: abs(actual - expected).n() < 1e-12 True The dual of the Schur cone is the "downward monotonic cone" @@ -566,7 +567,7 @@ def schur(ambient_dim=None, lattice=None): True sage: x = V.random_element() sage: y = V.random_element() - sage: majorized_by(x,y) == ( (y-x) in S ) # optional - sage.rings.number_fields + sage: majorized_by(x,y) == ( (y-x) in S ) True If a ``lattice`` was given, it is actually used:: diff --git a/src/sage/geometry/fan.py b/src/sage/geometry/fan.py index 3f04faf2e4d..258544012fe 100644 --- a/src/sage/geometry/fan.py +++ b/src/sage/geometry/fan.py @@ -196,11 +196,12 @@ We can also make ``fan3`` smooth, but it will take a bit more work:: + sage: # needs palp sage: cube = lattice_polytope.cross_polytope(3).polar() - sage: sk = cube.skeleton_points(2) # optional - palp - sage: rays = [cube.point(p) for p in sk] # optional - palp - sage: fan4 = fan3.subdivide(new_rays=rays) # optional - palp - sage: fan4.is_smooth() # optional - palp + sage: sk = cube.skeleton_points(2) + sage: rays = [cube.point(p) for p in sk] + sage: fan4 = fan3.subdivide(new_rays=rays) + sage: fan4.is_smooth() True Let's see how "different" are ``fan2`` and ``fan4``:: @@ -209,9 +210,9 @@ 6 sage: fan2.nrays() 8 - sage: fan4.ngenerating_cones() # optional - palp + sage: fan4.ngenerating_cones() # needs palp 48 - sage: fan4.nrays() # optional - palp + sage: fan4.nrays() # needs palp 26 Smoothness does not come for free! @@ -278,9 +279,9 @@ def is_Fan(x) -> bool: sage: from sage.geometry.fan import is_Fan sage: is_Fan(1) False - sage: fan = toric_varieties.P2().fan(); fan # optional - palp + sage: fan = toric_varieties.P2().fan(); fan # needs palp Rational polyhedral fan in 2-d lattice N - sage: is_Fan(fan) # optional - palp + sage: is_Fan(fan) # needs palp True """ return isinstance(x, RationalPolyhedralFan) @@ -503,7 +504,7 @@ def Fan(cones, rays=None, lattice=None, check=True, normalize=True, sage: fan = Fan([c1, c2], allow_arrangement=True) sage: fan.ngenerating_cones() 7 - sage: fan.plot() # optional - sage.plot + sage: fan.plot() # needs sage.plot Graphics3d Object Cones of different dimension:: @@ -523,7 +524,7 @@ def Fan(cones, rays=None, lattice=None, check=True, normalize=True, sage: c3 = Cone([[0, 1, 1], [1, 0, 1], [0, -1, 1], [-1, 0, 1]]) sage: c1 = Cone([[0, 0, 1]]) sage: fan1 = Fan([c1, c3], allow_arrangement=True) - sage: fan1.plot() # optional - sage.plot + sage: fan1.plot() # needs sage.plot Graphics3d Object A 3-d cone and two 2-d cones:: @@ -1027,12 +1028,13 @@ class Cone_of_fan(ConvexRationalPolyhedralCone): The intended way to get objects of this class is the following:: - sage: fan = toric_varieties.P1xP1().fan() # optional - palp - sage: cone = fan.generating_cone(0); cone # optional - palp + sage: # needs palp + sage: fan = toric_varieties.P1xP1().fan() + sage: cone = fan.generating_cone(0); cone 2-d cone of Rational polyhedral fan in 2-d lattice N - sage: cone.ambient_ray_indices() # optional - palp + sage: cone.ambient_ray_indices() (0, 2) - sage: cone.star_generator_indices() # optional - palp + sage: cone.star_generator_indices() (0,) """ @@ -1045,10 +1047,10 @@ def __init__(self, ambient, ambient_ray_indices): The following code is likely to construct an invalid object, we just test that creation of cones of fans is working:: - sage: fan = toric_varieties.P1xP1().fan() # optional - palp - sage: cone = sage.geometry.fan.Cone_of_fan(fan, (0,)); cone # optional - palp + sage: fan = toric_varieties.P1xP1().fan() # needs palp + sage: cone = sage.geometry.fan.Cone_of_fan(fan, (0,)); cone # needs palp 1-d cone of Rational polyhedral fan in 2-d lattice N - sage: TestSuite(cone).run() # optional - palp + sage: TestSuite(cone).run() # needs palp """ super().__init__(ambient=ambient, ambient_ray_indices=ambient_ray_indices) @@ -1065,11 +1067,12 @@ def _repr_(self) -> str: TESTS:: - sage: P1xP1 = toric_varieties.P1xP1() # optional - palp - sage: cone = P1xP1.fan().generating_cone(0) # optional - palp - sage: cone._repr_() # optional - palp + sage: # needs palp + sage: P1xP1 = toric_varieties.P1xP1() + sage: cone = P1xP1.fan().generating_cone(0) + sage: cone._repr_() '2-d cone of Rational polyhedral fan in 2-d lattice N' - sage: cone.facets()[0]._repr_() # optional - palp + sage: cone.facets()[0]._repr_() '1-d cone of Rational polyhedral fan in 2-d lattice N' """ # The base class would print "face of" instead of "cone of" @@ -1086,9 +1089,9 @@ def star_generator_indices(self): EXAMPLES:: - sage: P1xP1 = toric_varieties.P1xP1() # optional - palp - sage: cone = P1xP1.fan().generating_cone(0) # optional - palp - sage: cone.star_generator_indices() # optional - palp + sage: P1xP1 = toric_varieties.P1xP1() # needs palp + sage: cone = P1xP1.fan().generating_cone(0) # needs palp + sage: cone.star_generator_indices() # needs palp (0,) TESTS: @@ -1138,9 +1141,9 @@ def star_generators(self): EXAMPLES:: - sage: P1xP1 = toric_varieties.P1xP1() # optional - palp - sage: cone = P1xP1.fan().generating_cone(0) # optional - palp - sage: cone.star_generators() # optional - palp + sage: P1xP1 = toric_varieties.P1xP1() # needs palp + sage: cone = P1xP1.fan().generating_cone(0) # needs palp + sage: cone.star_generators() # needs palp (2-d cone of Rational polyhedral fan in 2-d lattice N,) """ if "_star_generators" not in self.__dict__: @@ -1394,8 +1397,8 @@ def _compute_cone_lattice(self): the common cases is a fan which is KNOWN to be complete, i.e. we do not even need to check if it is complete:: - sage: fan = toric_varieties.P1xP1().fan() # optional - palp - sage: fan.cone_lattice() # indirect doctest # optional - palp + sage: fan = toric_varieties.P1xP1().fan() # needs palp + sage: fan.cone_lattice() # indirect doctest # needs palp Finite lattice containing 10 elements with distinguished linear extension These 10 elements are: 1 origin, 4 rays, 4 generating cones, 1 fan. @@ -1625,9 +1628,9 @@ def support_contains(self, *args): False sage: f.support_contains(0) # 0 converts to the origin in the lattice True - sage: f.support_contains(1/2, sqrt(3)) # optional - sage.symbolic + sage: f.support_contains(1/2, sqrt(3)) # needs sage.symbolic True - sage: f.support_contains(-1/2, sqrt(3)) # optional - sage.symbolic + sage: f.support_contains(-1/2, sqrt(3)) # needs sage.symbolic False """ if len(args) == 1: @@ -1811,10 +1814,10 @@ def _ray_to_cones(self, i=None): EXAMPLES:: - sage: fan = toric_varieties.P1xP1().fan() # optional - palp - sage: fan._ray_to_cones(0) # optional - palp + sage: fan = toric_varieties.P1xP1().fan() # needs palp + sage: fan._ray_to_cones(0) # needs palp frozenset({0, 3}) - sage: fan._ray_to_cones() # optional - palp + sage: fan._ray_to_cones() # needs palp (frozenset({0, 3}), frozenset({1, 2}), frozenset({0, 1}), frozenset({2, 3})) """ # This function is close to self(1)[i].star_generator_indices(), but @@ -2123,9 +2126,9 @@ def cone_lattice(self): can (and will!) be computed in a much more efficient way, but the interface is exactly the same:: - sage: fan = toric_varieties.P1xP1().fan() # optional - palp - sage: L = fan.cone_lattice() # optional - palp - sage: for l in L.level_sets()[:-1]: # optional - palp + sage: fan = toric_varieties.P1xP1().fan() # needs palp + sage: L = fan.cone_lattice() # needs palp + sage: for l in L.level_sets()[:-1]: # needs palp ....: print([f.ambient_ray_indices() for f in l]) [()] [(0,), (1,), (2,), (3,)] @@ -2452,11 +2455,11 @@ def Gale_transform(self): EXAMPLES:: - sage: fan = toric_varieties.P1xP1().fan() # optional - palp - sage: fan.Gale_transform() # optional - palp + sage: fan = toric_varieties.P1xP1().fan() # needs palp + sage: fan.Gale_transform() # needs palp [ 1 1 0 0 -2] [ 0 0 1 1 -2] - sage: _.base_ring() # optional - palp + sage: _.base_ring() # needs palp Integer Ring """ m = self.rays().matrix().stack(matrix(ZZ, 1, self.lattice_dim())) @@ -2477,8 +2480,8 @@ def generating_cone(self, n): EXAMPLES:: - sage: fan = toric_varieties.P1xP1().fan() # optional - palp - sage: fan.generating_cone(0) # optional - palp + sage: fan = toric_varieties.P1xP1().fan() # needs palp + sage: fan.generating_cone(0) # needs palp 2-d cone of Rational polyhedral fan in 2-d lattice N """ return self._generating_cones[n] @@ -2493,8 +2496,8 @@ def generating_cones(self): EXAMPLES:: - sage: fan = toric_varieties.P1xP1().fan() # optional - palp - sage: fan.generating_cones() # optional - palp + sage: fan = toric_varieties.P1xP1().fan() # needs palp + sage: fan.generating_cones() # needs palp (2-d cone of Rational polyhedral fan in 2-d lattice N, 2-d cone of Rational polyhedral fan in 2-d lattice N, 2-d cone of Rational polyhedral fan in 2-d lattice N, @@ -2525,18 +2528,19 @@ def vertex_graph(self): EXAMPLES:: - sage: dP8 = toric_varieties.dP8() # optional - palp sage.graphs - sage: g = dP8.fan().vertex_graph(); g # optional - palp sage.graphs + sage: # needs palp + sage: dP8 = toric_varieties.dP8() + sage: g = dP8.fan().vertex_graph(); g Graph on 4 vertices - sage: set(dP8.fan(1)) == set(g.vertices(sort=False)) # optional - palp sage.graphs + sage: set(dP8.fan(1)) == set(g.vertices(sort=False)) True - sage: g.edge_labels() # all edge labels the same since every cone is smooth # optional - palp sage.graphs + sage: g.edge_labels() # all edge labels the same since every cone is smooth [(1, 0), (1, 0), (1, 0), (1, 0)] - sage: g = toric_varieties.Cube_deformation(10).fan().vertex_graph() # optional - sage.graphs - sage: g.automorphism_group().order() # optional - sage.graphs sage.groups + sage: g = toric_varieties.Cube_deformation(10).fan().vertex_graph() + sage: g.automorphism_group().order() # needs sage.groups 48 - sage: g.automorphism_group(edge_labels=True).order() # optional - sage.graphs sage.groups + sage: g.automorphism_group(edge_labels=True).order() # needs sage.groups 4 """ from sage.geometry.cone import classify_cone_2d @@ -2567,8 +2571,8 @@ def is_complete(self) -> bool: EXAMPLES:: - sage: fan = toric_varieties.P1xP1().fan() # optional - palp - sage: fan.is_complete() # optional - palp + sage: fan = toric_varieties.P1xP1().fan() # needs palp + sage: fan.is_complete() # needs palp True sage: cone1 = Cone([(1,0), (0,1)]) sage: cone2 = Cone([(-1,0)]) @@ -2750,8 +2754,8 @@ def _2d_echelon_forms(self): EXAMPLES:: - sage: fan = toric_varieties.dP8().fan() # optional - palp - sage: fan._2d_echelon_forms() # optional - palp + sage: fan = toric_varieties.dP8().fan() # needs palp + sage: fan._2d_echelon_forms() # needs palp frozenset({[ 1 0 -1 -1] [ 0 1 0 -1], [ 1 0 -1 0] [ 0 1 -1 -1], [ 1 0 -1 0] @@ -2772,8 +2776,8 @@ def _2d_echelon_form(self): EXAMPLES:: - sage: fan = toric_varieties.dP8().fan() # optional - palp - sage: fan._2d_echelon_form() # optional - palp + sage: fan = toric_varieties.dP8().fan() # needs palp + sage: fan._2d_echelon_form() # needs palp [ 1 0 -1 -1] [ 0 1 0 -1] """ @@ -2816,7 +2820,7 @@ def isomorphism(self, other): Domain fan: Rational polyhedral fan in 2-d lattice N Codomain fan: Rational polyhedral fan in 2-d lattice N - sage: fan1.isomorphism(toric_varieties.P2().fan()) # optional - palp + sage: fan1.isomorphism(toric_varieties.P2().fan()) # needs palp Traceback (most recent call last): ... FanNotIsomorphicError @@ -2838,8 +2842,8 @@ def is_simplicial(self) -> bool: EXAMPLES:: - sage: fan = toric_varieties.P1xP1().fan() # optional - palp - sage: fan.is_simplicial() # optional - palp + sage: fan = toric_varieties.P1xP1().fan() # needs palp + sage: fan.is_simplicial() # needs palp True sage: cone1 = Cone([(1,0), (0,1)]) sage: cone2 = Cone([(-1,0)]) @@ -2888,8 +2892,8 @@ def is_smooth(self, codim=None) -> bool: EXAMPLES:: - sage: fan = toric_varieties.P1xP1().fan() # optional - palp - sage: fan.is_smooth() # optional - palp + sage: fan = toric_varieties.P1xP1().fan() # needs palp + sage: fan.is_smooth() # needs palp True sage: cone1 = Cone([(1,0), (0,1)]) sage: cone2 = Cone([(-1,0)]) @@ -2957,8 +2961,8 @@ def ngenerating_cones(self): EXAMPLES:: - sage: fan = toric_varieties.P1xP1().fan() # optional - palp - sage: fan.ngenerating_cones() # optional - palp + sage: fan = toric_varieties.P1xP1().fan() # needs palp + sage: fan.ngenerating_cones() # needs palp 4 sage: cone1 = Cone([(1,0), (0,1)]) sage: cone2 = Cone([(-1,0)]) @@ -2983,8 +2987,8 @@ def plot(self, **options): EXAMPLES:: - sage: fan = toric_varieties.dP6().fan() # optional - palp - sage: fan.plot() # optional - palp sage.plot + sage: fan = toric_varieties.dP6().fan() # needs palp + sage: fan.plot() # needs palp sage.plot Graphics object consisting of 31 graphics primitives """ tp = ToricPlotter(options, self.lattice().degree(), self.rays()) @@ -3042,8 +3046,8 @@ def subdivide(self, new_rays=None, make_simplicial=False, We check that :trac:`11902` is fixed:: - sage: fan = toric_varieties.P2().fan() # optional - palp - sage: fan.subdivide(new_rays=[(0,0)]) # optional - palp + sage: fan = toric_varieties.P2().fan() # needs palp + sage: fan.subdivide(new_rays=[(0,0)]) # needs palp Traceback (most recent call last): ... ValueError: the origin cannot be used for fan subdivision! @@ -3319,18 +3323,19 @@ def oriented_boundary(self, cone): EXAMPLES:: - sage: fan = toric_varieties.P(3).fan() # optional - palp - sage: cone = fan(2)[0] # optional - palp - sage: bdry = fan.oriented_boundary(cone); bdry # optional - palp + sage: # needs palp + sage: fan = toric_varieties.P(3).fan() + sage: cone = fan(2)[0] + sage: bdry = fan.oriented_boundary(cone); bdry -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: bdry[0] # optional - palp + sage: bdry[0] (-1, 1-d cone of Rational polyhedral fan in 3-d lattice N) - sage: bdry[1] # optional - palp + sage: bdry[1] (1, 1-d cone of Rational polyhedral fan in 3-d lattice N) - sage: fan.oriented_boundary(bdry[0][1]) # optional - palp + sage: fan.oriented_boundary(bdry[0][1]) -0-d cone of Rational polyhedral fan in 3-d lattice N - sage: fan.oriented_boundary(bdry[1][1]) # optional - palp + sage: fan.oriented_boundary(bdry[1][1]) -0-d cone of Rational polyhedral fan in 3-d lattice N If you pass the fan itself, this method returns the @@ -3338,12 +3343,12 @@ def oriented_boundary(self, cone): order of the rays in :meth:`cone.ray_basis() ` :: - sage: fan.oriented_boundary(fan) # optional - palp + sage: fan.oriented_boundary(fan) # needs palp -3-d cone of Rational polyhedral fan in 3-d lattice N + 3-d cone of Rational polyhedral fan in 3-d lattice N - 3-d cone of Rational polyhedral fan in 3-d lattice N + 3-d cone of Rational polyhedral fan in 3-d lattice N - sage: [cone.rays().basis().matrix().det() # optional - palp + sage: [cone.rays().basis().matrix().det() # needs palp ....: for cone in fan.generating_cones()] [-1, 1, -1, 1] @@ -3358,9 +3363,9 @@ def oriented_boundary(self, cone): TESTS:: - sage: fan = toric_varieties.P2().fan() # optional - palp - sage: trivial_cone = fan(0)[0] # optional - palp - sage: fan.oriented_boundary(trivial_cone) # optional - palp + sage: fan = toric_varieties.P2().fan() # needs palp + sage: trivial_cone = fan(0)[0] # needs palp + sage: fan.oriented_boundary(trivial_cone) # needs palp 0 """ if cone is not self: @@ -3505,23 +3510,24 @@ def complex(self, base_ring=ZZ, extended=False): EXAMPLES:: - sage: fan = toric_varieties.P(3).fan() # optional - palp - sage: K_normal = fan.complex(); K_normal # optional - palp + sage: # needs palp + sage: fan = toric_varieties.P(3).fan() + sage: K_normal = fan.complex(); K_normal Chain complex with at most 4 nonzero terms over Integer Ring - sage: K_normal.homology() # optional - palp + sage: K_normal.homology() {0: Z, 1: 0, 2: 0, 3: 0} - sage: K_extended = fan.complex(extended=True); K_extended # optional - palp + sage: K_extended = fan.complex(extended=True); K_extended Chain complex with at most 5 nonzero terms over Integer Ring - sage: K_extended.homology() # optional - palp + sage: K_extended.homology() {-1: 0, 0: 0, 1: 0, 2: 0, 3: 0} Homology computations are much faster over `\QQ` if you do not care about the torsion coefficients:: - sage: toric_varieties.P2_123().fan().complex(extended=True, # optional - palp + sage: toric_varieties.P2_123().fan().complex(extended=True, # needs palp ....: base_ring=QQ) Chain complex with at most 4 nonzero terms over Rational Field - sage: _.homology() # optional - palp + sage: _.homology() # needs palp {-1: Vector space of dimension 0 over Rational Field, 0: Vector space of dimension 0 over Rational Field, 1: Vector space of dimension 0 over Rational Field, @@ -3606,17 +3612,17 @@ def discard_faces(cones): Consider all cones of a fan:: - sage: Sigma = toric_varieties.P2().fan() # optional - palp - sage: cones = flatten(Sigma.cones()) # optional - palp - sage: len(cones) # optional - palp + sage: Sigma = toric_varieties.P2().fan() # needs palp + sage: cones = flatten(Sigma.cones()) # needs palp + sage: len(cones) # needs palp 7 Most of them are not necessary to generate this fan:: sage: from sage.geometry.fan import discard_faces - sage: len(discard_faces(cones)) # optional - palp + sage: len(discard_faces(cones)) # needs palp 3 - sage: Sigma.ngenerating_cones() # optional - palp + sage: Sigma.ngenerating_cones() # needs palp 3 """ # Convert to a list or make a copy, so that the input is unchanged. diff --git a/src/sage/geometry/fan_isomorphism.py b/src/sage/geometry/fan_isomorphism.py index 0eb3b13d21c..2c69f06a71f 100644 --- a/src/sage/geometry/fan_isomorphism.py +++ b/src/sage/geometry/fan_isomorphism.py @@ -38,10 +38,10 @@ def fan_isomorphic_necessary_conditions(fan1, fan2): EXAMPLES:: - sage: fan1 = toric_varieties.P2().fan() # optional - palp - sage: fan2 = toric_varieties.dP8().fan() # optional - palp + sage: fan1 = toric_varieties.P2().fan() # needs palp sage.graphs + sage: fan2 = toric_varieties.dP8().fan() # needs palp sage.graphs sage: from sage.geometry.fan_isomorphism import fan_isomorphic_necessary_conditions - sage: fan_isomorphic_necessary_conditions(fan1, fan2) # optional - palp + sage: fan_isomorphic_necessary_conditions(fan1, fan2) # needs palp sage.graphs False """ if fan1.lattice_dim() != fan2.lattice_dim(): @@ -78,9 +78,9 @@ def fan_isomorphism_generator(fan1, fan2): EXAMPLES:: - sage: fan = toric_varieties.P2().fan() # optional - palp + sage: fan = toric_varieties.P2().fan() # needs palp sage.graphs sage: from sage.geometry.fan_isomorphism import fan_isomorphism_generator - sage: sorted(fan_isomorphism_generator(fan, fan)) # optional - palp + sage: sorted(fan_isomorphism_generator(fan, fan)) # needs palp sage.graphs [ [-1 -1] [-1 -1] [ 0 1] [0 1] [ 1 0] [1 0] [ 0 1], [ 1 0], [-1 -1], [1 0], [-1 -1], [0 1] @@ -93,7 +93,7 @@ def fan_isomorphism_generator(fan1, fan2): ....: Cone([m1*vector([-1,-14]), m1*vector([-100, -5])])]) sage: fan2 = Fan([Cone([m2*vector([23, 14]), m2*vector([ 3,100])]), ....: Cone([m2*vector([-1,-14]), m2*vector([-100, -5])])]) - sage: sorted(fan_isomorphism_generator(fan1, fan2)) + sage: sorted(fan_isomorphism_generator(fan1, fan2)) # needs sage.graphs [ [-12 1 -5] [ -4 0 -1] @@ -111,24 +111,24 @@ def fan_isomorphism_generator(fan1, fan2): ....: Cone([m1*vector([1,1]), m1*vector([0,1])])]) sage: fan2 = Fan([Cone([m2*vector([1,0]), m2*vector([1,1])]), ....: Cone([m2*vector([1,1]), m2*vector([0,1])])]) - sage: sorted(fan_isomorphism_generator(fan0, fan0)) + sage: sorted(fan_isomorphism_generator(fan0, fan0)) # needs sage.graphs [ [0 1] [1 0] [1 0], [0 1] ] - sage: sorted(fan_isomorphism_generator(fan1, fan1)) + sage: sorted(fan_isomorphism_generator(fan1, fan1)) # needs sage.graphs [ [ -3 -20 28] [1 0 0] [ -1 -4 7] [0 1 0] [ -1 -5 8], [0 0 1] ] - sage: sorted(fan_isomorphism_generator(fan1, fan2)) + sage: sorted(fan_isomorphism_generator(fan1, fan2)) # needs sage.graphs [ [-24 -3 7] [-12 1 -5] [ -7 -1 2] [ -4 0 -1] [ -8 -1 2], [ -5 0 -1] ] - sage: sorted(fan_isomorphism_generator(fan2, fan1)) + sage: sorted(fan_isomorphism_generator(fan2, fan1)) # needs sage.graphs [ [ 0 1 -1] [ 0 1 -1] [ 1 -13 8] [ 2 -8 1] @@ -216,14 +216,14 @@ def find_isomorphism(fan1, fan2, check=False): sage: fan2 = Fan(cones, [vector(r)*m for r in rays]) sage: from sage.geometry.fan_isomorphism import find_isomorphism - sage: find_isomorphism(fan1, fan2, check=True) # optional - sage.graphs + sage: find_isomorphism(fan1, fan2, check=True) # needs sage.graphs Fan morphism defined by the matrix [-2 3] [ 1 -1] Domain fan: Rational polyhedral fan in 2-d lattice N Codomain fan: Rational polyhedral fan in 2-d lattice N - sage: find_isomorphism(fan1, toric_varieties.P2().fan()) # optional - palp + sage: find_isomorphism(fan1, toric_varieties.P2().fan()) # needs palp sage.graphs Traceback (most recent call last): ... FanNotIsomorphicError @@ -232,7 +232,7 @@ def find_isomorphism(fan1, fan2, check=False): ....: rays=[(-1,-1,0),(-1,-1,3),(-1,1,-1),(-1,3,-1),(0,2,-1),(1,-1,1)]) sage: fan2 = Fan(cones=[[0,2,3,5],[0,1,4,5],[0,1,2],[3,4,5]], ....: rays=[(-1,-1,-1),(-1,-1,0),(-1,1,-1),(0,2,-1),(1,-1,1),(3,-1,-1)]) - sage: fan1.is_isomorphic(fan2) + sage: fan1.is_isomorphic(fan2) # needs sage.graphs True """ generator = fan_isomorphism_generator(fan1, fan2) @@ -311,14 +311,14 @@ def fan_2d_echelon_forms(fan): EXAMPLES:: - sage: fan = toric_varieties.P2().fan() # optional - palp + sage: fan = toric_varieties.P2().fan() # needs palp sage.graphs sage: from sage.geometry.fan_isomorphism import fan_2d_echelon_forms - sage: fan_2d_echelon_forms(fan) # optional - palp + sage: fan_2d_echelon_forms(fan) # needs palp sage.graphs frozenset({[ 1 0 -1] [ 0 1 -1]}) - sage: fan = toric_varieties.dP7().fan() # optional - palp - sage: sorted(fan_2d_echelon_forms(fan)) # optional - palp + sage: fan = toric_varieties.dP7().fan() # needs palp sage.graphs + sage: sorted(fan_2d_echelon_forms(fan)) # needs palp sage.graphs [ [ 1 0 -1 -1 0] [ 1 0 -1 -1 0] [ 1 0 -1 -1 1] [ 1 0 -1 0 1] [ 0 1 0 -1 -1], [ 0 1 1 0 -1], [ 0 1 1 0 -1], [ 0 1 0 -1 -1], @@ -334,10 +334,10 @@ def fan_2d_echelon_forms(fan): sage: fan1 = Fan(cones, rays) sage: from sage.geometry.fan_isomorphism import fan_2d_echelon_form, fan_2d_echelon_forms sage: echelon_forms = fan_2d_echelon_forms(fan1) - sage: S4 = CyclicPermutationGroup(4) + sage: S4 = CyclicPermutationGroup(4) # needs sage.groups sage: rays.reverse() sage: cones = [(3,1), (1,2), (2,0), (0,3)] - sage: for i in range(100): + sage: for i in range(100): # needs sage.groups ....: m = random_matrix(ZZ,2,2) ....: if abs(det(m)) != 1: continue ....: perm = S4.random_element() @@ -382,9 +382,9 @@ def fan_2d_echelon_form(fan): EXAMPLES:: - sage: fan = toric_varieties.P2().fan() # optional - palp + sage: fan = toric_varieties.P2().fan() # needs palp sage.graphs sage: from sage.geometry.fan_isomorphism import fan_2d_echelon_form - sage: fan_2d_echelon_form(fan) # optional - palp + sage: fan_2d_echelon_form(fan) # needs palp sage.graphs [ 1 0 -1] [ 0 1 -1] """ diff --git a/src/sage/geometry/fan_morphism.py b/src/sage/geometry/fan_morphism.py index 2302c7551ee..1d3cd1db886 100644 --- a/src/sage/geometry/fan_morphism.py +++ b/src/sage/geometry/fan_morphism.py @@ -319,15 +319,15 @@ def __mul__(self, right): EXAMPLES:: sage: A2 = toric_varieties.A2() - sage: P3 = toric_varieties.P(3) # optional - palp + sage: P3 = toric_varieties.P(3) # needs palp sage: m = matrix([(2,0,0), (1,1,0)]) - sage: phi = A2.hom(m, P3).fan_morphism(); phi # optional - palp + sage: phi = A2.hom(m, P3).fan_morphism(); phi # needs palp Fan morphism defined by the matrix [2 0 0] [1 1 0] Domain fan: Rational polyhedral fan in 2-d lattice N Codomain fan: Rational polyhedral fan in 3-d lattice N - sage: prod(phi.factor()) # indirect test # optional - palp + sage: prod(phi.factor()) # indirect test # needs palp Fan morphism defined by the matrix [2 0 0] [1 1 0] @@ -529,13 +529,14 @@ def _ray_index_map(self): TESTS:: - sage: Sigma = toric_varieties.dP8().fan() # optional - palp + sage: # needs palp + sage: Sigma = toric_varieties.dP8().fan() sage: Sigma_p = toric_varieties.P1().fan() - sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) # optional - palp - sage: phi._ray_index_map() # optional - palp + sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) + sage: phi._ray_index_map() (-1, 1, -1, 0) - sage: xi = FanMorphism(matrix([[1, 0]]), Sigma_p, Sigma) # optional - palp - sage: xi._ray_index_map() # optional - palp + sage: xi = FanMorphism(matrix([[1, 0]]), Sigma_p, Sigma) + sage: xi._ray_index_map() Traceback (most recent call last): ... ValueError: ray #1 is mapped into a 2-d cone! @@ -1040,32 +1041,33 @@ def index(self, cone=None): EXAMPLES:: - sage: Sigma = toric_varieties.dP8().fan() # optional - palp + sage: # needs palp + sage: Sigma = toric_varieties.dP8().fan() sage: Sigma_p = toric_varieties.P1().fan() - sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) # optional - palp - sage: phi.index() # optional - palp + sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) + sage: phi.index() 1 - sage: psi = FanMorphism(matrix([[2], [-2]]), Sigma, Sigma_p) # optional - palp - sage: psi.index() # optional - palp + sage: psi = FanMorphism(matrix([[2], [-2]]), Sigma, Sigma_p) + sage: psi.index() 2 - sage: xi = FanMorphism(matrix([[1, 0]]), Sigma_p, Sigma) # optional - palp - sage: xi.index() # optional - palp + sage: xi = FanMorphism(matrix([[1, 0]]), Sigma_p, Sigma) + sage: xi.index() +Infinity Infinite index in the last example indicates that the image has positive codimension in the codomain. Let's look at the rays of our fans:: - sage: Sigma_p.rays() + sage: Sigma_p.rays() # needs palp N( 1), N(-1) in 1-d lattice N - sage: Sigma.rays() # optional - palp + sage: Sigma.rays() # needs palp N( 1, 1), N( 0, 1), N(-1, -1), N( 1, 0) in 2-d lattice N - sage: xi.factor()[0].domain_fan().rays() # optional - palp + sage: xi.factor()[0].domain_fan().rays() # needs palp N(-1, 0), N( 1, 0) in Sublattice @@ -1081,25 +1083,26 @@ def index(self, cone=None): 1-d cones are ``None``, except for one which is infinite, and all indices over 2-d cones are ``None``, except for one which is 1:: - sage: [xi.index(cone) for cone in Sigma(1)] # optional - palp + sage: [xi.index(cone) for cone in Sigma(1)] # needs palp [None, None, None, +Infinity] - sage: [xi.index(cone) for cone in Sigma(2)] # optional - palp + sage: [xi.index(cone) for cone in Sigma(2)] # needs palp [None, 1, None, None] TESTS:: - sage: Sigma = toric_varieties.dP8().fan() # optional - palp + sage: # needs palp + sage: Sigma = toric_varieties.dP8().fan() sage: Sigma_p = toric_varieties.Cube_nonpolyhedral().fan() sage: m = matrix([[2,6,10], [7,11,13]]) - sage: zeta = FanMorphism(m, Sigma, Sigma_p, subdivide=True) # optional - palp - sage: [zeta.index(cone) for cone in flatten(Sigma_p.cones())] # optional - palp + sage: zeta = FanMorphism(m, Sigma, Sigma_p, subdivide=True) + sage: [zeta.index(cone) for cone in flatten(Sigma_p.cones())] [+Infinity, None, None, None, None, None, None, None, None, None, 4, 4, None, 4, None, None, 2, None, 4, None, 4, 1, 1, 1, 1, 1, 1] - sage: zeta = prod(zeta.factor()[1:]) # optional - palp - sage: Sigma_p = zeta.codomain_fan() # optional - palp - sage: [zeta.index(cone) for cone in flatten(Sigma_p.cones())] # optional - palp + sage: zeta = prod(zeta.factor()[1:]) + sage: Sigma_p = zeta.codomain_fan() + sage: [zeta.index(cone) for cone in flatten(Sigma_p.cones())] [4, 4, 4, 1, 4, 4, 4, 1, 1, 1, 1, 1, 1] - sage: zeta.index() == zeta.index(Sigma_p(0)[0]) # optional - palp + sage: zeta.index() == zeta.index(Sigma_p(0)[0]) True """ if cone is None: @@ -1130,14 +1133,15 @@ def is_birational(self): EXAMPLES:: - sage: Sigma = toric_varieties.dP8().fan() # optional - palp + sage: # needs palp + sage: Sigma = toric_varieties.dP8().fan() sage: Sigma_p = toric_varieties.P1().fan() - sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) # optional - palp - sage: psi = FanMorphism(matrix([[2], [-2]]), Sigma, Sigma_p) # optional - palp - sage: xi = FanMorphism(matrix([[1, 0]]), Sigma_p, Sigma) # optional - palp - sage: phi.index(), psi.index(), xi.index() # optional - palp + sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) + sage: psi = FanMorphism(matrix([[2], [-2]]), Sigma, Sigma_p) + sage: xi = FanMorphism(matrix([[1, 0]]), Sigma_p, Sigma) + sage: phi.index(), psi.index(), xi.index() (1, 2, +Infinity) - sage: phi.is_birational(), psi.is_birational(), xi.is_birational() # optional - palp + sage: phi.is_birational(), psi.is_birational(), xi.is_birational() (True, False, False) """ return self.index() == 1 @@ -1178,26 +1182,27 @@ def is_bundle(self): We consider several maps between fans of a del Pezzo surface and the projective line:: - sage: Sigma = toric_varieties.dP8().fan() # optional - palp + sage: # needs palp + sage: Sigma = toric_varieties.dP8().fan() sage: Sigma_p = toric_varieties.P1().fan() - sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) # optional - palp - sage: psi = FanMorphism(matrix([[2], [-2]]), Sigma, Sigma_p) # optional - palp - sage: xi = FanMorphism(matrix([[1, 0]]), Sigma_p, Sigma) # optional - palp - sage: phi.is_bundle() # optional - palp + sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) + sage: psi = FanMorphism(matrix([[2], [-2]]), Sigma, Sigma_p) + sage: xi = FanMorphism(matrix([[1, 0]]), Sigma_p, Sigma) + sage: phi.is_bundle() True - sage: phi.is_fibration() # optional - palp + sage: phi.is_fibration() True - sage: phi.index() # optional - palp + sage: phi.index() 1 - sage: psi.is_bundle() # optional - palp + sage: psi.is_bundle() False - sage: psi.is_fibration() # optional - palp + sage: psi.is_fibration() True - sage: psi.index() # optional - palp + sage: psi.index() 2 - sage: xi.is_fibration() # optional - palp + sage: xi.is_fibration() False - sage: xi.index() # optional - palp + sage: xi.index() +Infinity The first of these maps induces not only a fibration, but a fiber @@ -1270,26 +1275,27 @@ def is_fibration(self): We consider several maps between fans of a del Pezzo surface and the projective line:: - sage: Sigma = toric_varieties.dP8().fan() # optional - palp + sage: # needs palp + sage: Sigma = toric_varieties.dP8().fan() sage: Sigma_p = toric_varieties.P1().fan() - sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) # optional - palp - sage: psi = FanMorphism(matrix([[2], [-2]]), Sigma, Sigma_p) # optional - palp - sage: xi = FanMorphism(matrix([[1, 0]]), Sigma_p, Sigma) # optional - palp - sage: phi.is_bundle() # optional - palp + sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) + sage: psi = FanMorphism(matrix([[2], [-2]]), Sigma, Sigma_p) + sage: xi = FanMorphism(matrix([[1, 0]]), Sigma_p, Sigma) + sage: phi.is_bundle() True - sage: phi.is_fibration() # optional - palp + sage: phi.is_fibration() True - sage: phi.index() # optional - palp + sage: phi.index() 1 - sage: psi.is_bundle() # optional - palp + sage: psi.is_bundle() False - sage: psi.is_fibration() # optional - palp + sage: psi.is_fibration() True - sage: psi.index() # optional - palp + sage: psi.index() 2 - sage: xi.is_fibration() # optional - palp + sage: xi.is_fibration() False - sage: xi.index() # optional - palp + sage: xi.index() +Infinity The first of these maps induces not only a fibration, but a fiber @@ -1384,9 +1390,9 @@ def is_injective(self): We also embed the affine plane into the projective one:: - sage: P2 = toric_varieties.P(2).fan() # optional - palp + sage: P2 = toric_varieties.P(2).fan() # needs palp sage: m = identity_matrix(2) - sage: FanMorphism(m, A2, P2).is_injective() # optional - palp + sage: FanMorphism(m, A2, P2).is_injective() # needs palp True """ if self.matrix().index_in_saturation() != 1: @@ -1564,15 +1570,16 @@ def preimage_cones(self, cone): We check that reviewer's example from :trac:`9972` is handled correctly:: + sage: # needs palp sage: N1 = ToricLattice(1) sage: N2 = ToricLattice(2) sage: Hom21 = Hom(N2, N1) sage: pr = Hom21([N1.0,0]) - sage: P1xP1 = toric_varieties.P1xP1() # optional - palp - sage: f = FanMorphism(pr, P1xP1.fan()) # optional - palp - sage: c = f.image_cone(Cone([(1,0), (0,1)])); c # optional - palp + sage: P1xP1 = toric_varieties.P1xP1() + sage: f = FanMorphism(pr, P1xP1.fan()) + sage: c = f.image_cone(Cone([(1,0), (0,1)])); c 1-d cone of Rational polyhedral fan in 1-d lattice N - sage: f.preimage_cones(c) # optional - palp + sage: f.preimage_cones(c) (1-d cone of Rational polyhedral fan in 2-d lattice N, 2-d cone of Rational polyhedral fan in 2-d lattice N, 2-d cone of Rational polyhedral fan in 2-d lattice N) @@ -1678,8 +1685,8 @@ def primitive_preimage_cones(self, cone): Consider a projection of a del Pezzo surface onto the projective line:: - sage: Sigma = toric_varieties.dP6().fan() # optional - palp - sage: Sigma.rays() # optional - palp + sage: Sigma = toric_varieties.dP6().fan() # needs palp + sage: Sigma.rays() # needs palp N( 0, 1), N(-1, 0), N(-1, -1), @@ -1688,7 +1695,7 @@ def primitive_preimage_cones(self, cone): N( 1, 1) in 2-d lattice N sage: Sigma_p = toric_varieties.P1().fan() - sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) # optional - palp + sage: phi = FanMorphism(matrix([[1], [-1]]), Sigma, Sigma_p) # needs palp Under this map, one pair of rays is mapped to the origin, one in the positive direction, and one in the negative one. Also three @@ -1696,28 +1703,28 @@ def primitive_preimage_cones(self, cone): the negative one, so there are 5 preimage cones corresponding to either of the rays of the codomain fan ``Sigma_p``:: - sage: len(phi.preimage_cones(Cone([(1,)]))) # optional - palp + sage: len(phi.preimage_cones(Cone([(1,)]))) # needs palp 5 Yet only rays are primitive:: - sage: phi.primitive_preimage_cones(Cone([(1,)])) # optional - palp + sage: phi.primitive_preimage_cones(Cone([(1,)])) # needs palp (1-d cone of Rational polyhedral fan in 2-d lattice N, 1-d cone of Rational polyhedral fan in 2-d lattice N) Since all primitive cones are mapped onto their images bijectively, we get a fibration:: - sage: phi.is_fibration() # optional - palp + sage: phi.is_fibration() # needs palp True But since there are several primitive cones corresponding to the same cone of the codomain fan, this map is not a bundle, even though its index is 1:: - sage: phi.is_bundle() # optional - palp + sage: phi.is_bundle() # needs palp False - sage: phi.index() # optional - palp + sage: phi.index() # needs palp 1 """ sigma_p = self._codomain_fan.embed(cone) # Necessary if used as a key @@ -1771,10 +1778,10 @@ def factor(self): coordinate planes":: sage: A2 = toric_varieties.A2() - sage: P3 = toric_varieties.P(3) # optional - palp + sage: P3 = toric_varieties.P(3) # needs palp sage: m = matrix([(2,0,0), (1,1,0)]) - sage: phi = A2.hom(m, P3) # optional - palp - sage: phi.as_polynomial_map() # optional - palp + sage: phi = A2.hom(m, P3) # needs palp + sage: phi.as_polynomial_map() # needs palp Scheme morphism: From: 2-d affine toric variety To: 3-d CPR-Fano toric variety covered by 4 affine patches @@ -1783,18 +1790,19 @@ def factor(self): Now we will work with the underlying fan morphism:: - sage: phi = phi.fan_morphism(); phi # optional - palp + sage: # needs palp + sage: phi = phi.fan_morphism(); phi Fan morphism defined by the matrix [2 0 0] [1 1 0] Domain fan: Rational polyhedral fan in 2-d lattice N Codomain fan: Rational polyhedral fan in 3-d lattice N - sage: phi.is_surjective(), phi.is_birational(), phi.is_injective() # optional - palp + sage: phi.is_surjective(), phi.is_birational(), phi.is_injective() (False, False, False) - sage: phi_i, phi_b, phi_s = phi.factor() # optional - palp - sage: phi_s.is_surjective(), phi_b.is_birational(), phi_i.is_injective() # optional - palp + sage: phi_i, phi_b, phi_s = phi.factor() + sage: phi_s.is_surjective(), phi_b.is_birational(), phi_i.is_injective() (True, True, True) - sage: prod(phi.factor()) == phi # optional - palp + sage: prod(phi.factor()) == phi True Double cover (surjective):: @@ -1803,26 +1811,26 @@ def factor(self): N(1, 0), N(0, 1) in 2-d lattice N - sage: phi_s # optional - palp + sage: phi_s # needs palp Fan morphism defined by the matrix [2 0] [1 1] Domain fan: Rational polyhedral fan in 2-d lattice N Codomain fan: Rational polyhedral fan in Sublattice - sage: phi_s.codomain_fan().rays() # optional - palp + sage: phi_s.codomain_fan().rays() # needs palp N(1, 0, 0), N(1, 1, 0) in Sublattice Blowup chart (birational):: - sage: phi_b # optional - palp + sage: phi_b # needs palp Fan morphism defined by the matrix [1 0] [0 1] Domain fan: Rational polyhedral fan in Sublattice Codomain fan: Rational polyhedral fan in Sublattice - sage: phi_b.codomain_fan().rays() # optional - palp + sage: phi_b.codomain_fan().rays() # needs palp N(-1, -1, 0), N( 0, 1, 0), N( 1, 0, 0) @@ -1830,13 +1838,13 @@ def factor(self): Coordinate plane inclusion (injective):: - sage: phi_i # optional - palp + sage: phi_i # needs palp Fan morphism defined by the matrix [1 0 0] [0 1 0] Domain fan: Rational polyhedral fan in Sublattice Codomain fan: Rational polyhedral fan in 3-d lattice N - sage: phi.codomain_fan().rays() # optional - palp + sage: phi.codomain_fan().rays() # needs palp N( 1, 0, 0), N( 0, 1, 0), N( 0, 0, 1), @@ -1845,16 +1853,17 @@ def factor(self): TESTS:: - sage: phi_s.matrix() * phi_b.matrix() * phi_i.matrix() == m # optional - palp + sage: phi_s.matrix() * phi_b.matrix() * phi_i.matrix() == m # needs palp True - sage: phi.domain_fan() is phi_s.domain_fan() # optional - palp + sage: # needs palp + sage: phi.domain_fan() is phi_s.domain_fan() True - sage: phi_s.codomain_fan() is phi_b.domain_fan() # optional - palp + sage: phi_s.codomain_fan() is phi_b.domain_fan() True - sage: phi_b.codomain_fan() is phi_i.domain_fan() # optional - palp + sage: phi_b.codomain_fan() is phi_i.domain_fan() True - sage: phi_i.codomain_fan() is phi.codomain_fan() # optional - palp + sage: phi_i.codomain_fan() is phi.codomain_fan() True sage: trivialfan2 = Fan([], [], lattice=ToricLattice(2)) diff --git a/src/sage/geometry/hasse_diagram.py b/src/sage/geometry/hasse_diagram.py index f40560f30fe..d30f08ac8d5 100644 --- a/src/sage/geometry/hasse_diagram.py +++ b/src/sage/geometry/hasse_diagram.py @@ -104,9 +104,9 @@ def lattice_from_incidences(atom_to_coatoms, coatom_to_atoms, and we can compute the lattice as :: sage: from sage.geometry.cone import lattice_from_incidences - sage: L = lattice_from_incidences(atom_to_coatoms, coatom_to_atoms); L # optional - sage.graphs + sage: L = lattice_from_incidences(atom_to_coatoms, coatom_to_atoms); L # needs sage.graphs Finite lattice containing 8 elements with distinguished linear extension - sage: for level in L.level_sets(): print(level) # optional - sage.graphs + sage: for level in L.level_sets(): print(level) # needs sage.graphs [((), (0, 1, 2))] [((0,), (0, 1)), ((1,), (0, 2)), ((2,), (1, 2))] [((0, 1), (0,)), ((0, 2), (1,)), ((1, 2), (2,))] diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py b/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py index 45c8efb11ed..9f6d5725f68 100644 --- a/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +++ b/src/sage/geometry/hyperbolic_space/hyperbolic_geodesic.py @@ -24,7 +24,7 @@ :: - sage: g.plot(axes=True) # optional - sage.plot + sage: g.plot(axes=True) # needs sage.plot Graphics object consisting of 2 graphics primitives .. PLOT:: @@ -37,7 +37,7 @@ sage: g = HyperbolicPlane().UHP().get_geodesic(I, 3 + I) sage: g.length() arccosh(11/2) - sage: g.plot(axes=True) # optional - sage.plot + sage: g.plot(axes=True) # needs sage.plot Graphics object consisting of 2 graphics primitives .. PLOT:: @@ -49,7 +49,7 @@ sage: g = HyperbolicPlane().UHP().get_geodesic(I, 3*I) sage: g Geodesic in UHP from I to 3*I - sage: g.plot() # optional - sage.plot + sage: g.plot() # needs sage.plot Graphics object consisting of 2 graphics primitives .. PLOT:: @@ -1126,7 +1126,7 @@ def plot(self, boundary=True, **options): EXAMPLES:: sage: UHP = HyperbolicPlane().UHP() - sage: UHP.get_geodesic(0, 1).plot() # optional - sage.plot + sage: UHP.get_geodesic(0, 1).plot() # needs sage.plot Graphics object consisting of 2 graphics primitives .. PLOT:: @@ -1137,7 +1137,7 @@ def plot(self, boundary=True, **options): :: - sage: UHP.get_geodesic(I, 3+4*I).plot(linestyle="dashed", color="brown") # optional - sage.plot + sage: UHP.get_geodesic(I, 3+4*I).plot(linestyle="dashed", color="brown") # needs sage.plot Graphics object consisting of 2 graphics primitives .. PLOT:: @@ -1148,7 +1148,7 @@ def plot(self, boundary=True, **options): :: - sage: UHP.get_geodesic(1, infinity).plot(color='orange') # optional - sage.plot + sage: UHP.get_geodesic(1, infinity).plot(color='orange') # needs sage.plot Graphics object consisting of 2 graphics primitives .. PLOT:: @@ -1162,25 +1162,25 @@ def plot(self, boundary=True, **options): Plotting a line with ``boundary=True``. :: sage: g = HyperbolicPlane().UHP().get_geodesic(0, I) - sage: g.plot() # optional - sage.plot + sage: g.plot() # needs sage.plot Graphics object consisting of 2 graphics primitives Plotting a line with ``boundary=False``. :: sage: g = HyperbolicPlane().UHP().get_geodesic(0, I) - sage: g.plot(boundary=False) # optional - sage.plot + sage: g.plot(boundary=False) # needs sage.plot Graphics object consisting of 1 graphics primitive Plotting a circle with ``boundary=True``. :: sage: g = HyperbolicPlane().UHP().get_geodesic(-3, 19) - sage: g.plot() # optional - sage.plot + sage: g.plot() # needs sage.plot Graphics object consisting of 2 graphics primitives Plotting a circle with ``boundary=False``. :: sage: g = HyperbolicPlane().UHP().get_geodesic(3, 4) - sage: g.plot(boundary=False) # optional - sage.plot + sage: g.plot(boundary=False) # needs sage.plot Graphics object consisting of 1 graphics primitive """ @@ -2202,7 +2202,7 @@ def plot(self, boundary=True, **options): First some lines:: sage: PD = HyperbolicPlane().PD() - sage: PD.get_geodesic(0, 1).plot() # optional - sage.plot + sage: PD.get_geodesic(0, 1).plot() # needs sage.plot Graphics object consisting of 2 graphics primitives .. PLOT:: @@ -2211,7 +2211,7 @@ def plot(self, boundary=True, **options): :: - sage: PD.get_geodesic(0, 0.3+0.8*I).plot() # optional - sage.plot + sage: PD.get_geodesic(0, 0.3+0.8*I).plot() # needs sage.plot Graphics object consisting of 2 graphics primitives .. PLOT:: @@ -2221,15 +2221,15 @@ def plot(self, boundary=True, **options): Then some generic geodesics:: - sage: PD.get_geodesic(-0.5, 0.3+0.4*I).plot() # optional - sage.plot + sage: PD.get_geodesic(-0.5, 0.3+0.4*I).plot() # needs sage.plot Graphics object consisting of 2 graphics primitives sage: g = PD.get_geodesic(-1, exp(3*I*pi/7)) - sage: G = g.plot(linestyle="dashed",color="red"); G # optional - sage.plot + sage: G = g.plot(linestyle="dashed",color="red"); G # needs sage.plot Graphics object consisting of 2 graphics primitives sage: h = PD.get_geodesic(exp(2*I*pi/11), exp(1*I*pi/11)) - sage: H = h.plot(thickness=6, color="orange"); H # optional - sage.plot + sage: H = h.plot(thickness=6, color="orange"); H # needs sage.plot Graphics object consisting of 2 graphics primitives - sage: show(G+H) # optional - sage.plot + sage: show(G+H) # needs sage.plot .. PLOT:: @@ -2293,7 +2293,7 @@ class HyperbolicGeodesicKM(HyperbolicGeodesic): sage: KM = HyperbolicPlane().KM() sage: g = KM.get_geodesic((0.1,0.9),(-0.1,-0.9)) sage: h = KM.get_geodesic((-0.707106781,-0.707106781),(0.707106781,-0.707106781)) - sage: P = g.plot(color='orange')+h.plot(); P # optional - sage.plot + sage: P = g.plot(color='orange')+h.plot(); P # needs sage.plot Graphics object consisting of 4 graphics primitives .. PLOT:: @@ -2313,7 +2313,7 @@ def plot(self, boundary=True, **options): EXAMPLES:: - sage: HyperbolicPlane().KM().get_geodesic(0, 1).plot() # optional - sage.plot + sage: HyperbolicPlane().KM().get_geodesic(0, 1).plot() # needs sage.plot Graphics object consisting of 2 graphics primitives .. PLOT:: @@ -2424,7 +2424,7 @@ def plot(self, show_hyperboloid=True, **graphics_options): sage: from sage.geometry.hyperbolic_space.hyperbolic_geodesic \ ....: import * sage: g = HyperbolicPlane().HM().random_geodesic() - sage: g.plot() # optional - sage.plot + sage: g.plot() # needs sage.plot Graphics3d Object .. PLOT:: diff --git a/src/sage/geometry/hyperplane_arrangement/affine_subspace.py b/src/sage/geometry/hyperplane_arrangement/affine_subspace.py index 3b024b6f419..7c1065553c4 100644 --- a/src/sage/geometry/hyperplane_arrangement/affine_subspace.py +++ b/src/sage/geometry/hyperplane_arrangement/affine_subspace.py @@ -33,8 +33,8 @@ True sage: c < b False - sage: A = AffineSubspace([8,38,21,250], VectorSpace(GF(19),4)) # optional - sage.libs.pari - sage: A # optional - sage.libs.pari + sage: A = AffineSubspace([8,38,21,250], VectorSpace(GF(19),4)) + sage: A Affine space p + W where: p = (8, 0, 2, 3) W = Vector space of dimension 4 over Finite Field of size 19 @@ -384,9 +384,9 @@ def intersection(self, other): [] sage: A.intersection(C).intersection(B) - sage: D = AffineSubspace([1,2,3], VectorSpace(GF(5),3)) # optional - sage.libs.pari - sage: E = AffineSubspace([3,4,5], VectorSpace(GF(5),3)) # optional - sage.libs.pari - sage: D.intersection(E) # optional - sage.libs.pari + sage: D = AffineSubspace([1,2,3], VectorSpace(GF(5),3)) + sage: E = AffineSubspace([3,4,5], VectorSpace(GF(5),3)) + sage: D.intersection(E) Affine space p + W where: p = (3, 4, 0) W = Vector space of dimension 3 over Finite Field of size 5 diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index 7cc2b479573..ee8962019ae 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -60,42 +60,43 @@ The default base field is `\QQ`, the rational numbers. Finite fields are also supported:: - sage: H. = HyperplaneArrangements(GF(5)) # optional - sage.rings.finite_rings - sage: a = H([(1,2,3), 4], [(5,6,7), 8]); a # optional - sage.rings.finite_rings + sage: H. = HyperplaneArrangements(GF(5)) + sage: a = H([(1,2,3), 4], [(5,6,7), 8]); a Arrangement Number fields are also possible:: + sage: # needs sage.rings.number_field sage: x = polygen(QQ, 'x') - sage: NF. = NumberField(x**4 - 5*x**2 + 5, embedding=1.90) # optional - sage.rings.number_field - sage: H. = HyperplaneArrangements(NF) # optional - sage.rings.number_field - sage: A = H([[(-a**3 + 3*a, -a**2 + 4), 1], [(a**3 - 4*a, -1), 1], # optional - sage.rings.number_field + sage: NF. = NumberField(x**4 - 5*x**2 + 5, embedding=1.90) + sage: H. = HyperplaneArrangements(NF) + sage: A = H([[(-a**3 + 3*a, -a**2 + 4), 1], [(a**3 - 4*a, -1), 1], ....: [(0, 2*a**2 - 6), 1], [(-a**3 + 4*a, -1), 1], ....: [(a**3 - 3*a, -a**2 + 4), 1]]) - sage: A # optional - sage.rings.number_field + sage: A Arrangement of 5 hyperplanes of dimension 2 and rank 2 - sage: A.base_ring() # optional - sage.rings.number_field + sage: A.base_ring() Number Field in a with defining polynomial x^4 - 5*x^2 + 5 with a = 1.902113032590308? Notation (iii): a list or tuple of hyperplanes:: - sage: H. = HyperplaneArrangements(GF(5)) # optional - sage.rings.finite_rings - sage: k = [x+i for i in range(4)]; k # optional - sage.rings.finite_rings + sage: H. = HyperplaneArrangements(GF(5)) + sage: k = [x+i for i in range(4)]; k [Hyperplane x + 0*y + 0*z + 0, Hyperplane x + 0*y + 0*z + 1, Hyperplane x + 0*y + 0*z + 2, Hyperplane x + 0*y + 0*z + 3] - sage: H(k) # optional - sage.rings.finite_rings + sage: H(k) Arrangement Notation (iv): using the library of arrangements:: - sage: hyperplane_arrangements.braid(4) # optional - sage.graphs + sage: hyperplane_arrangements.braid(4) # needs sage.graphs Arrangement of 6 hyperplanes of dimension 4 and rank 3 - sage: hyperplane_arrangements.semiorder(3) # optional - sage.combinat + sage: hyperplane_arrangements.semiorder(3) Arrangement of 6 hyperplanes of dimension 3 and rank 2 - sage: hyperplane_arrangements.graphical(graphs.PetersenGraph()) # optional - sage.graphs + sage: hyperplane_arrangements.graphical(graphs.PetersenGraph()) # needs sage.graphs Arrangement of 15 hyperplanes of dimension 10 and rank 9 - sage: hyperplane_arrangements.Ish(5) # optional - sage.combinat + sage: hyperplane_arrangements.Ish(5) Arrangement of 20 hyperplanes of dimension 5 and rank 4 Notation (v): from the bounding hyperplanes of a polyhedron:: @@ -107,21 +108,23 @@ New arrangements from old:: - sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: b = a.add_hyperplane([4, 1, 2, 3]) # optional - sage.graphs - sage: b # optional - sage.graphs + sage: # needs sage.graphs + sage: a = hyperplane_arrangements.braid(3) + sage: b = a.add_hyperplane([4, 1, 2, 3]) + sage: b Arrangement - sage: c = b.deletion([4, 1, 2, 3]) # optional - sage.graphs - sage: a == c # optional - sage.graphs + sage: c = b.deletion([4, 1, 2, 3]) + sage: a == c True - sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs sage.combinat - sage: b = a.union(hyperplane_arrangements.semiorder(3)) # optional - sage.graphs sage.combinat - sage: b == a | hyperplane_arrangements.semiorder(3) # alternate syntax # optional - sage.graphs sage.combinat + sage: # needs sage.combinat sage.graphs + sage: a = hyperplane_arrangements.braid(3) + sage: b = a.union(hyperplane_arrangements.semiorder(3)) + sage: b == a | hyperplane_arrangements.semiorder(3) # alternate syntax True - sage: b == hyperplane_arrangements.Catalan(3) # optional - sage.graphs sage.combinat + sage: b == hyperplane_arrangements.Catalan(3) True - sage: a # optional - sage.graphs sage.combinat + sage: a Arrangement sage: a = hyperplane_arrangements.coordinate(4) @@ -139,24 +142,25 @@ normal space (actually, it is a bit more complicated over finite fields):: - sage: a = hyperplane_arrangements.braid(4); a # optional - sage.graphs + sage: # needs sage.graphs + sage: a = hyperplane_arrangements.braid(4); a Arrangement of 6 hyperplanes of dimension 4 and rank 3 - sage: a.is_essential() # optional - sage.graphs + sage: a.is_essential() False - sage: a.rank() < a.dimension() # double-check # optional - sage.graphs + sage: a.rank() < a.dimension() # double-check True - sage: a.essentialization() # optional - sage.graphs + sage: a.essentialization() Arrangement of 6 hyperplanes of dimension 3 and rank 3 The connected components of the complement of the hyperplanes of an arrangement in `\RR^n` are called the *regions* of the arrangement:: - sage: a = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: b = a.essentialization(); b # optional - sage.combinat + sage: a = hyperplane_arrangements.semiorder(3) + sage: b = a.essentialization(); b Arrangement of 6 hyperplanes of dimension 2 and rank 2 - sage: b.n_regions() # optional - sage.combinat + sage: b.n_regions() 19 - sage: b.regions() # optional - sage.combinat + sage: b.regions() (A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 6 vertices, A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices, A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices, @@ -184,9 +188,9 @@ A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices, A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices, A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices) - sage: b.n_bounded_regions() # optional - sage.combinat + sage: b.n_bounded_regions() 7 - sage: a.unbounded_regions() # optional - sage.combinat + sage: a.unbounded_regions() (A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line, A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices, 1 ray, 1 line, A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line, @@ -203,13 +207,14 @@ The distance between regions is defined as the number of hyperplanes separating them. For example:: - sage: r1 = b.regions()[0] # optional - sage.combinat - sage: r2 = b.regions()[1] # optional - sage.combinat - sage: b.distance_between_regions(r1, r2) # optional - sage.combinat + sage: # needs sage.combinat + sage: r1 = b.regions()[0] + sage: r2 = b.regions()[1] + sage: b.distance_between_regions(r1, r2) 1 - sage: [hyp for hyp in b if b.is_separating_hyperplane(r1, r2, hyp)] # optional - sage.combinat + sage: [hyp for hyp in b if b.is_separating_hyperplane(r1, r2, hyp)] [Hyperplane 2*t1 + t2 + 1] - sage: b.distance_enumerator(r1) # generating function for distances from r1 # optional - sage.combinat + sage: b.distance_enumerator(r1) # generating function for distances from r1 6*x^3 + 6*x^2 + 6*x + 1 .. NOTE:: @@ -223,11 +228,12 @@ ordered by reverse inclusion. It includes the ambient space of the arrangement (as the intersection over the empty set):: - sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: p = a.intersection_poset() # optional - sage.graphs - sage: p.is_ranked() # optional - sage.graphs + sage: # needs sage.graphs + sage: a = hyperplane_arrangements.braid(3) + sage: p = a.intersection_poset() + sage: p.is_ranked() True - sage: p.order_polytope() # optional - sage.graphs + sage: p.order_polytope() A 5-dimensional polyhedron in ZZ^5 defined as the convex hull of 10 vertices The characteristic polynomial is a basic invariant of a hyperplane @@ -241,19 +247,20 @@ :meth:`~HyperplaneArrangementElement.intersection_poset` of the arrangement and `\mu` is the Möbius function of `P`:: + sage: # long time sage: a = hyperplane_arrangements.semiorder(5) - sage: a.characteristic_polynomial() # long time (about a second on Core i7) + sage: a.characteristic_polynomial() # about a second on Core i7 x^5 - 20*x^4 + 180*x^3 - 790*x^2 + 1380*x - sage: a.poincare_polynomial() # long time + sage: a.poincare_polynomial() 1380*x^4 + 790*x^3 + 180*x^2 + 20*x + 1 - sage: a.n_regions() # long time + sage: a.n_regions() 2371 - sage: charpoly = a.characteristic_polynomial() # long time - sage: charpoly(-1) # long time + sage: charpoly = a.characteristic_polynomial() + sage: charpoly(-1) -2371 - sage: a.n_bounded_regions() # long time + sage: a.n_bounded_regions() 751 - sage: charpoly(1) # long time + sage: charpoly(1) 751 For finer invariants derived from the intersection poset, see @@ -263,16 +270,16 @@ Miscellaneous methods (see documentation for an explanation):: sage: a = hyperplane_arrangements.semiorder(3) - sage: a.has_good_reduction(5) # optional - sage.rings.finite_rings + sage: a.has_good_reduction(5) # needs sage.rings.finite_rings True - sage: b = a.change_ring(GF(5)) # optional - sage.rings.finite_rings - sage: pa = a.intersection_poset() - sage: pb = b.intersection_poset() # optional - sage.rings.finite_rings - sage: pa.is_isomorphic(pb) # optional - sage.rings.finite_rings + sage: b = a.change_ring(GF(5)) + sage: pa = a.intersection_poset() # needs sage.graphs + sage: pb = b.intersection_poset() # needs sage.rings.finite_rings + sage: pa.is_isomorphic(pb) # needs sage.graphs sage.rings.finite_rings True - sage: a.face_vector() + sage: a.face_vector() # needs sage.graphs (0, 12, 30, 19) - sage: a.face_vector() + sage: a.face_vector() # needs sage.graphs (0, 12, 30, 19) sage: a.is_central() False @@ -394,13 +401,14 @@ def __init__(self, parent, hyperplanes, check=True, backend=None): It is possible to specify a backend for polyhedral computations:: - sage: R. = QuadraticField(5) # optional - sage.rings.number_field - sage: H = HyperplaneArrangements(R, names='xyz') # optional - sage.rings.number_field - sage: x, y, z = H.gens() # optional - sage.rings.number_field - sage: A = H(sqrt5*x + 2*y + 3*z, backend='normaliz') # optional - sage.rings.number_field - sage: A.backend() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: R. = QuadraticField(5) + sage: H = HyperplaneArrangements(R, names='xyz') + sage: x, y, z = H.gens() + sage: A = H(sqrt5*x + 2*y + 3*z, backend='normaliz') + sage: A.backend() 'normaliz' - sage: A.regions()[0].backend() # optional - pynormaliz sage.rings.number_field + sage: A.regions()[0].backend() # optional - pynormaliz 'normaliz' """ super().__init__(parent) @@ -424,8 +432,8 @@ def _first_ngens(self, n): EXAMPLES:: - sage: a. = hyperplane_arrangements.braid(3) # indirect doctest # optional - sage.graphs - sage: (x, y) == a._first_ngens(2) # optional - sage.graphs + sage: a. = hyperplane_arrangements.braid(3) # indirect doctest # needs sage.graphs + sage: (x, y) == a._first_ngens(2) # needs sage.graphs True """ return self.parent()._first_ngens(n) @@ -570,14 +578,15 @@ def rank(self): sage: A.rank() 2 - sage: B = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: B.hyperplanes() # optional - sage.graphs + sage: # needs sage.graphs + sage: B = hyperplane_arrangements.braid(3) + sage: B.hyperplanes() (Hyperplane 0*t0 + t1 - t2 + 0, Hyperplane t0 - t1 + 0*t2 + 0, Hyperplane t0 + 0*t1 - t2 + 0) - sage: B.dimension() # optional - sage.graphs + sage: B.dimension() 3 - sage: B.rank() # optional - sage.graphs + sage: B.rank() 2 sage: p = polytopes.simplex(5, project=True) @@ -689,7 +698,7 @@ def plot(self, **kwds): EXAMPLES:: sage: L. = HyperplaneArrangements(QQ) - sage: L(x, y, x+y-2).plot() # optional - sage.plot + sage: L(x, y, x+y-2).plot() # needs sage.plot Graphics object consisting of 3 graphics primitives """ from sage.geometry.hyperplane_arrangement.plot import plot @@ -720,20 +729,21 @@ def cone(self, variable='t'): EXAMPLES:: - sage: a. = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: b = a.cone() # optional - sage.combinat - sage: a.characteristic_polynomial().factor() # optional - sage.combinat + sage: # needs sage.combinat + sage: a. = hyperplane_arrangements.semiorder(3) + sage: b = a.cone() + sage: a.characteristic_polynomial().factor() x * (x^2 - 6*x + 12) - sage: b.characteristic_polynomial().factor() # optional - sage.combinat + sage: b.characteristic_polynomial().factor() (x - 1) * x * (x^2 - 6*x + 12) - sage: a.hyperplanes() # optional - sage.combinat + sage: a.hyperplanes() (Hyperplane 0*x + y - z - 1, Hyperplane 0*x + y - z + 1, Hyperplane x - y + 0*z - 1, Hyperplane x - y + 0*z + 1, Hyperplane x + 0*y - z - 1, Hyperplane x + 0*y - z + 1) - sage: b.hyperplanes() # optional - sage.combinat + sage: b.hyperplanes() (Hyperplane -t + 0*x + y - z + 0, Hyperplane -t + x - y + 0*z + 0, Hyperplane -t + x + 0*y - z + 0, @@ -781,21 +791,22 @@ def intersection_poset(self, element_label="int"): of hyperplanes of the arrangement. :: sage: A = hyperplane_arrangements.coordinate(2) - sage: L = A.intersection_poset(); L # optional - sage.combinat + sage: L = A.intersection_poset(); L # needs sage.combinat Finite poset containing 4 elements - sage: sorted(L) # optional - sage.combinat + sage: sorted(L) # needs sage.combinat [0, 1, 2, 3] - sage: L.level_sets() # optional - sage.combinat + sage: L.level_sets() # needs sage.combinat [[0], [1, 2], [3]] :: - sage: A = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: L = A.intersection_poset(); L # optional - sage.combinat + sage: # needs sage.combinat + sage: A = hyperplane_arrangements.semiorder(3) + sage: L = A.intersection_poset(); L Finite poset containing 19 elements - sage: sorted(L) # optional - sage.combinat + sage: sorted(L) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18] - sage: [sorted(level_set) for level_set in L.level_sets()] # optional - sage.combinat + sage: [sorted(level_set) for level_set in L.level_sets()] [[0], [1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]] By passing the argument ``element_label="subset"``, each element of the @@ -803,9 +814,9 @@ def intersection_poset(self, element_label="int"): whose intersection is said element. The index of a hyperplane is its index in ``self.hyperplanes()``. :: - sage: A = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: L = A.intersection_poset(element_label='subset') # optional - sage.combinat - sage: [sorted(level, key=sorted) for level in L.level_sets()] # optional - sage.combinat + sage: A = hyperplane_arrangements.semiorder(3) + sage: L = A.intersection_poset(element_label='subset') # needs sage.combinat + sage: [sorted(level, key=sorted) for level in L.level_sets()] # needs sage.combinat [[{}], [{0}, {1}, {2}, {3}, {4}, {5}], [{0, 2}, {0, 3}, {0, 4}, {0, 5}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {2, 4}, {2, 5}, {3, 4}, {3, 5}]] @@ -814,17 +825,17 @@ def intersection_poset(self, element_label="int"): sage: H. = HyperplaneArrangements(QQ) sage: A = H((y, y-1, y+1, x-y, x+y)) - sage: L = A.intersection_poset(element_label='subset') # optional - sage.combinat - sage: sorted(L, key=sorted) # optional - sage.combinat + sage: L = A.intersection_poset(element_label='subset') # needs sage.combinat + sage: sorted(L, key=sorted) # needs sage.combinat [{}, {0}, {0, 3}, {0, 4}, {1}, {1, 3, 4}, {2}, {2, 3}, {2, 4}, {3}, {4}] One can instead use affine subspaces as elements, which is what is used to compute the poset in the first place:: sage: A = hyperplane_arrangements.coordinate(2) - sage: L = A.intersection_poset(element_label='subspace'); L # optional - sage.combinat + sage: L = A.intersection_poset(element_label='subspace'); L # needs sage.combinat Finite poset containing 4 elements - sage: sorted(L, key=lambda S: (S.dimension(), # optional - sage.combinat + sage: sorted(L, key=lambda S: (S.dimension(), # needs sage.combinat ....: S.linear_part().basis_matrix())) [Affine space p + W where: p = (0, 0) @@ -905,7 +916,7 @@ def _slow_characteristic_polynomial(self): EXAMPLES:: sage: a = hyperplane_arrangements.coordinate(2) - sage: a._slow_characteristic_polynomial() # optional - sage.combinat + sage: a._slow_characteristic_polynomial() # needs sage.combinat x^2 - 2*x + 1 """ from sage.rings.polynomial.polynomial_ring import polygen @@ -1050,20 +1061,21 @@ def restriction(self, hyperplane): EXAMPLES:: - sage: A. = hyperplane_arrangements.braid(4); A # optional - sage.graphs + sage: # needs sage.graphs + sage: A. = hyperplane_arrangements.braid(4); A Arrangement of 6 hyperplanes of dimension 4 and rank 3 - sage: H = A[0]; H # optional - sage.graphs + sage: H = A[0]; H Hyperplane 0*u + 0*x + y - z + 0 - sage: R = A.restriction(H); R # optional - sage.graphs + sage: R = A.restriction(H); R Arrangement - sage: D = A.deletion(H); D # optional - sage.graphs + sage: D = A.deletion(H); D Arrangement of 5 hyperplanes of dimension 4 and rank 3 - sage: ca = A.characteristic_polynomial() # optional - sage.graphs - sage: cr = R.characteristic_polynomial() # optional - sage.graphs - sage: cd = D.characteristic_polynomial() # optional - sage.graphs - sage: ca # optional - sage.graphs + sage: ca = A.characteristic_polynomial() + sage: cr = R.characteristic_polynomial() + sage: cd = D.characteristic_polynomial() + sage: ca x^4 - 6*x^3 + 11*x^2 - 6*x - sage: cd - cr # optional - sage.graphs + sage: cd - cr x^4 - 6*x^3 + 11*x^2 - 6*x .. SEEALSO:: @@ -1130,7 +1142,7 @@ def change_ring(self, base_ring): sage: H. = HyperplaneArrangements(QQ) sage: A = H([(1,1), 0], [(2,3), -1]) - sage: A.change_ring(FiniteField(2)) # optional - sage.rings.finite_rings + sage: A.change_ring(FiniteField(2)) Arrangement TESTS: @@ -1158,38 +1170,39 @@ def n_regions(self): EXAMPLES:: - sage: A = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: A.n_regions() # optional - sage.combinat + sage: A = hyperplane_arrangements.semiorder(3) + sage: A.n_regions() 19 TESTS:: sage: H. = HyperplaneArrangements(QQ) sage: A = H([(1,1), 0], [(2,3), -1], [(4,5), 3]) - sage: B = A.change_ring(FiniteField(7)) # optional - sage.rings.finite_rings - sage: B.n_regions() # optional - sage.rings.finite_rings + sage: B = A.change_ring(FiniteField(7)) + sage: B.n_regions() Traceback (most recent call last): ... TypeError: base field must have characteristic zero Check that :trac:`30749` is fixed:: + sage: # needs sage.rings.number_field sage: R. = QQ[] - sage: v1 = AA.polynomial_root(AA.common_polynomial(y^2 - 3), # optional - sage.rings.number_field + sage: v1 = AA.polynomial_root(AA.common_polynomial(y^2 - 3), ....: RIF(RR(1.7320508075688772), RR(1.7320508075688774))) - sage: v2 = QQbar.polynomial_root(AA.common_polynomial(y^4 - y^2 + 1), # optional - sage.rings.number_field + sage: v2 = QQbar.polynomial_root(AA.common_polynomial(y^4 - y^2 + 1), ....: CIF(RIF(RR(0.8660254037844386), RR(0.86602540378443871)), ....: RIF(-RR(0.50000000000000011), -RR(0.49999999999999994)))) - sage: my_vectors = (vector(AA, [-v1, -1, 1]), vector(AA, [0, 2, 1]), vector(AA, [v1, -1, 1]), # optional - sage.rings.number_field + sage: my_vectors = (vector(AA, [-v1, -1, 1]), vector(AA, [0, 2, 1]), vector(AA, [v1, -1, 1]), ....: vector(AA, [1, 0, 0]), vector(AA, [1/2, AA(-1/2*v2^3 + v2),0]), ....: vector(AA, [-1/2, AA(-1/2*v2^3 + v2), 0])) - sage: H = HyperplaneArrangements(AA, names='xyz') # optional - sage.rings.number_field - sage: x,y,z = H.gens() # optional - sage.rings.number_field - sage: A = H(backend="normaliz") # optional - pynormaliz # optional - sage.rings.number_field - sage: for v in my_vectors: # optional - pynormaliz # optional - sage.rings.number_field + sage: H = HyperplaneArrangements(AA, names='xyz') + sage: x,y,z = H.gens() + sage: A = H(backend="normaliz") # optional - pynormaliz + sage: for v in my_vectors: # optional - pynormaliz ....: a, b, c = v ....: A = A.add_hyperplane(a*x + b*y + c*z) - sage: A.n_regions() # optional - pynormaliz # optional - sage.rings.number_field + sage: A.n_regions() # optional - pynormaliz 24 """ if self.base_ring().characteristic() != 0: @@ -1209,16 +1222,16 @@ def n_bounded_regions(self): EXAMPLES:: - sage: A = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: A.n_bounded_regions() # optional - sage.combinat + sage: A = hyperplane_arrangements.semiorder(3) + sage: A.n_bounded_regions() 7 TESTS:: sage: H. = HyperplaneArrangements(QQ) sage: A = H([(1,1),0], [(2,3),-1], [(4,5),3]) - sage: B = A.change_ring(FiniteField(7)) # optional - sage.rings.finite_rings - sage: B.n_bounded_regions() # optional - sage.rings.finite_rings + sage: B = A.change_ring(FiniteField(7)) + sage: B.n_bounded_regions() Traceback (most recent call last): ... TypeError: base field must have characteristic zero @@ -1248,15 +1261,16 @@ def has_good_reduction(self, p): EXAMPLES:: - sage: a = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: a.has_good_reduction(5) # optional - sage.combinat sage.rings.finite_rings + sage: # needs sage.combinat + sage: a = hyperplane_arrangements.semiorder(3) + sage: a.has_good_reduction(5) True - sage: a.has_good_reduction(3) # optional - sage.combinat sage.rings.finite_rings + sage: a.has_good_reduction(3) False - sage: b = a.change_ring(GF(3)) # optional - sage.combinat sage.rings.finite_rings - sage: a.characteristic_polynomial() # optional - sage.combinat sage.rings.finite_rings + sage: b = a.change_ring(GF(3)) + sage: a.characteristic_polynomial() x^3 - 6*x^2 + 12*x - sage: b.characteristic_polynomial() # not equal to that for a # optional - sage.combinat sage.rings.finite_rings + sage: b.characteristic_polynomial() # not equal to that for a x^3 - 6*x^2 + 10*x """ if self.base_ring() != QQ: @@ -1279,11 +1293,11 @@ def is_linear(self): EXAMPLES:: - sage: a = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: a.is_linear() # optional - sage.combinat + sage: a = hyperplane_arrangements.semiorder(3) + sage: a.is_linear() False - sage: b = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: b.is_linear() # optional - sage.graphs + sage: b = hyperplane_arrangements.braid(3) # needs sage.graphs + sage: b.is_linear() # needs sage.graphs True sage: H. = HyperplaneArrangements(QQ) @@ -1345,8 +1359,8 @@ def is_central(self, certificate=False): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(2) # optional - sage.graphs - sage: a.is_central() # optional - sage.graphs + sage: a = hyperplane_arrangements.braid(2) # needs sage.graphs + sage: a.is_central() # needs sage.graphs True The Catalan arrangement in dimension 3 is not central:: @@ -1421,15 +1435,15 @@ def center(self): The Shi arrangement in dimension 3 has an empty center:: - sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat - sage: A.center() # optional - sage.combinat + sage: A = hyperplane_arrangements.Shi(3) + sage: A.center() The empty polyhedron in QQ^3 The Braid arrangement in dimension 3 has a center that is neither empty nor full-dimensional:: - sage: A = hyperplane_arrangements.braid(3) # optional - sage.combinat - sage: A.center() # optional - sage.combinat + sage: A = hyperplane_arrangements.braid(3) # needs sage.combinat + sage: A.center() # needs sage.combinat A 1-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex and 1 line """ return self.is_central(certificate=True)[1] @@ -1459,7 +1473,7 @@ def is_simplicial(self): sage: A = H([[0,1,1,1], [0,1,2,3], [0,1,3,2], [0,2,1,3]]) sage: A.is_simplicial() False - sage: hyperplane_arrangements.braid(3).is_simplicial() # optional - sage.graphs + sage: hyperplane_arrangements.braid(3).is_simplicial() # needs sage.graphs True """ # if the arr is not essential, grab the essential version and check there. @@ -1485,10 +1499,10 @@ def essentialization(self): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: a.is_essential() # optional - sage.graphs + sage: a = hyperplane_arrangements.braid(3) # needs sage.graphs + sage: a.is_essential() # needs sage.graphs False - sage: a.essentialization() # optional - sage.graphs + sage: a.essentialization() # needs sage.graphs Arrangement sage: H. = HyperplaneArrangements(QQ) @@ -1501,13 +1515,13 @@ def essentialization(self): Hyperplane arrangements in 1-dimensional linear space over Rational Field with coordinate x - sage: H. = HyperplaneArrangements(GF(2)) # optional - sage.rings.finite_rings - sage: C = H([(1,1),1], [(1,1),0]) # optional - sage.rings.finite_rings - sage: C.essentialization() # optional - sage.rings.finite_rings + sage: H. = HyperplaneArrangements(GF(2)) + sage: C = H([(1,1),1], [(1,1),0]) + sage: C.essentialization() Arrangement - sage: h = hyperplane_arrangements.semiorder(4) # optional - sage.combinat - sage: h.essentialization() # optional - sage.combinat + sage: h = hyperplane_arrangements.semiorder(4) + sage: h.essentialization() Arrangement of 12 hyperplanes of dimension 3 and rank 3 TESTS:: @@ -1593,9 +1607,9 @@ def sign_vector(self, p): TESTS:: - sage: H. = HyperplaneArrangements(GF(3)) # optional - sage.rings.finite_rings - sage: A = H(x, y) # optional - sage.rings.finite_rings - sage: A.sign_vector([1, 2]) # optional - sage.rings.finite_rings + sage: H. = HyperplaneArrangements(GF(3)) + sage: A = H(x, y) + sage: A.sign_vector([1, 2]) Traceback (most recent call last): ... ValueError: characteristic must be zero @@ -1622,8 +1636,8 @@ def face_vector(self): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat - sage: A.face_vector() # optional - sage.combinat + sage: A = hyperplane_arrangements.Shi(3) + sage: A.face_vector() # needs sage.combinat (0, 6, 21, 16) """ m = self.whitney_data()[0] @@ -1662,7 +1676,7 @@ def _parallel_hyperplanes(self): (Hyperplane x + 2*y + 0, (1, 2), 0), (Hyperplane 2*x + 4*y + 1, (1, 2), 1/2)) - sage: hyperplane_arrangements.Shi(3)._parallel_hyperplanes() # optional - sage.combinat + sage: hyperplane_arrangements.Shi(3)._parallel_hyperplanes() (((Hyperplane 0*t0 + t1 - t2 - 1, (0, 1, -1), -1), (Hyperplane 0*t0 + t1 - t2 + 0, (0, 1, -1), 0)), ((Hyperplane t0 - t1 + 0*t2 - 1, (1, -1, 0), -1), @@ -1705,14 +1719,15 @@ def vertices(self, exclude_sandwiched=False): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3).essentialization() # optional - sage.combinat - sage: A.dimension() # optional - sage.combinat + sage: # needs sage.combinat + sage: A = hyperplane_arrangements.Shi(3).essentialization() + sage: A.dimension() 2 - sage: A.face_vector() # optional - sage.combinat + sage: A.face_vector() (6, 21, 16) - sage: A.vertices() # optional - sage.combinat + sage: A.vertices() ((-2/3, 1/3), (-1/3, -1/3), (0, -1), (0, 0), (1/3, -2/3), (2/3, -1/3)) - sage: point2d(A.vertices(), size=20) + A.plot() # optional - sage.combinat sage.plot + sage: point2d(A.vertices(), size=20) + A.plot() # needs sage.plot Graphics object consisting of 7 graphics primitives sage: H. = HyperplaneArrangements(QQ) @@ -1782,7 +1797,7 @@ def _make_region(self, hyperplanes): Checks that it creates the regions with the appropriate backend:: - sage: h = H(x,backend='normaliz') # optional - pynormaliz + sage: h = H(x,backend='normaliz') sage: h._make_region([x, 1-x, y, 1-y]).backend() # optional - pynormaliz 'normaliz' """ @@ -1808,8 +1823,8 @@ def regions(self): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(2) # optional - sage.graphs - sage: a.regions() # optional - sage.graphs + sage: a = hyperplane_arrangements.braid(2) # needs sage.graphs + sage: a.regions() # needs sage.graphs (A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line, A 2-dimensional polyhedron in QQ^2 defined @@ -1863,21 +1878,22 @@ def regions(self): It is possible to specify the backend:: - sage: K. = CyclotomicField(9) # optional - sage.rings.number_field - sage: L. = NumberField((q + q**(-1)).minpoly(), # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = CyclotomicField(9) + sage: L. = NumberField((q + q**(-1)).minpoly(), ....: embedding=AA(q + q**-1)) - sage: norms = [[1, 1/3*(-2*r9**2-r9+1), 0], # optional - sage.rings.number_field + sage: norms = [[1, 1/3*(-2*r9**2-r9+1), 0], ....: [1, -r9**2 - r9, 0], ....: [1, -r9**2 + 1, 0], ....: [1, -r9**2, 0], ....: [1, r9**2 - 4, -r9**2+3]] - sage: H. = HyperplaneArrangements(L) # optional - sage.rings.number_field - sage: A = H(backend='normaliz') # optional - sage.rings.number_field - sage: for v in norms: # optional - sage.rings.number_field + sage: H. = HyperplaneArrangements(L) + sage: A = H(backend='normaliz') + sage: for v in norms: ....: a,b,c = v ....: A = A.add_hyperplane(a*x + b*y + c*z) - sage: R = A.regions() # optional - pynormaliz sage.rings.number_field - sage: R[0].backend() # optional - pynormaliz sage.rings.number_field + sage: R = A.regions() # optional - pynormaliz + sage: R[0].backend() # optional - pynormaliz 'normaliz' TESTS:: @@ -1987,23 +2003,24 @@ def poset_of_regions(self, B=None, numbered_labels=True): sage: H. = HyperplaneArrangements(QQ) sage: A = H([[0,1,1,1], [0,1,2,3]]) - sage: A.poset_of_regions() # optional - sage.combinat + sage: A.poset_of_regions() # needs sage.combinat Finite poset containing 4 elements - sage: A = hyperplane_arrangements.braid(3) # optional - sage.combinat sage.graphs - sage: A.poset_of_regions() # optional - sage.combinat sage.graphs + sage: # needs sage.combinat sage.graphs + sage: A = hyperplane_arrangements.braid(3) + sage: A.poset_of_regions() Finite poset containing 6 elements - sage: A.poset_of_regions(numbered_labels=False) # optional - sage.combinat sage.graphs + sage: A.poset_of_regions(numbered_labels=False) Finite poset containing 6 elements - sage: A = hyperplane_arrangements.braid(4) # optional - sage.combinat sage.graphs - sage: A.poset_of_regions() # optional - sage.combinat sage.graphs + sage: A = hyperplane_arrangements.braid(4) + sage: A.poset_of_regions() Finite poset containing 24 elements sage: H. = HyperplaneArrangements(QQ) sage: A = H([[0,1,1,1], [0,1,2,3], [0,1,3,2], [0,2,1,3]]) - sage: R = A.regions() # optional - sage.combinat - sage: base_region = R[3] # optional - sage.combinat - sage: A.poset_of_regions(B=base_region) # optional - sage.combinat + sage: R = A.regions() + sage: base_region = R[3] + sage: A.poset_of_regions(B=base_region) # needs sage.combinat Finite poset containing 14 elements """ from sage.combinat.posets.posets import Poset @@ -2108,24 +2125,25 @@ def closed_faces(self, labelled=True): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(2) # optional - sage.graphs - sage: a.hyperplanes() # optional - sage.graphs + sage: # needs sage.graphs + sage: a = hyperplane_arrangements.braid(2) + sage: a.hyperplanes() (Hyperplane t0 - t1 + 0,) - sage: a.closed_faces() # optional - sage.graphs + sage: a.closed_faces() (((0,), A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line), ((1,), A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line), ((-1,), A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line)) - sage: a.closed_faces(labelled=False) # optional - sage.graphs + sage: a.closed_faces(labelled=False) (A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line, A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line, A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line) - sage: [(v, F, F.representative_point()) for v, F in a.closed_faces()] # optional - sage.graphs + sage: [(v, F, F.representative_point()) for v, F in a.closed_faces()] [((0,), A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line, (0, 0)), ((1,), A 2-dimensional polyhedron in QQ^2 defined @@ -2157,12 +2175,12 @@ def closed_faces(self, labelled=True): ((-1, -1), A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays, (-1, -2))] - sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: a.hyperplanes() # optional - sage.graphs + sage: a = hyperplane_arrangements.braid(3) # needs sage.graphs + sage: a.hyperplanes() # needs sage.graphs (Hyperplane 0*t0 + t1 - t2 + 0, Hyperplane t0 - t1 + 0*t2 + 0, Hyperplane t0 + 0*t1 - t2 + 0) - sage: [(v, F, F.representative_point()) for v, F in a.closed_faces()] # optional - sage.graphs + sage: [(v, F, F.representative_point()) for v, F in a.closed_faces()] # needs sage.graphs [((0, 0, 0), A 1-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex and 1 line, (0, 0, 0)), ((0, 1, 1), A 2-dimensional polyhedron in QQ^3 defined @@ -2200,10 +2218,10 @@ def closed_faces(self, labelled=True): ....: LHS = Qx.sum(x ** F[1].dim() for F in a.closed_faces()) ....: return LHS == RHS sage: a = hyperplane_arrangements.Catalan(2) - sage: test_number(a) # optional - sage.combinat + sage: test_number(a) # needs sage.combinat True - sage: a = hyperplane_arrangements.Shi(3) # optional - sage.combinat - sage: test_number(a) # long time # optional - sage.combinat + sage: a = hyperplane_arrangements.Shi(3) + sage: test_number(a) # long time # needs sage.combinat True TESTS: @@ -2338,27 +2356,28 @@ def face_product(self, F, G, normalize=True): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: a.hyperplanes() # optional - sage.graphs + sage: # needs sage.graphs + sage: a = hyperplane_arrangements.braid(3) + sage: a.hyperplanes() (Hyperplane 0*t0 + t1 - t2 + 0, Hyperplane t0 - t1 + 0*t2 + 0, Hyperplane t0 + 0*t1 - t2 + 0) - sage: faces = {F0: F1 for F0, F1 in a.closed_faces()} # optional - sage.graphs - sage: xGyEz = faces[(0, 1, 1)] # closed face x >= y = z # optional - sage.graphs - sage: xGyEz.representative_point() # optional - sage.graphs + sage: faces = {F0: F1 for F0, F1 in a.closed_faces()} + sage: xGyEz = faces[(0, 1, 1)] # closed face x >= y = z + sage: xGyEz.representative_point() (0, -1, -1) - sage: xGyEz = faces[(0, 1, 1)] # closed face x >= y = z # optional - sage.graphs - sage: xGyEz.representative_point() # optional - sage.graphs + sage: xGyEz = faces[(0, 1, 1)] # closed face x >= y = z + sage: xGyEz.representative_point() (0, -1, -1) - sage: yGxGz = faces[(1, -1, 1)] # closed face y >= x >= z # optional - sage.graphs - sage: xGyGz = faces[(1, 1, 1)] # closed face x >= y >= z # optional - sage.graphs - sage: a.face_product(xGyEz, yGxGz) == xGyGz # optional - sage.graphs + sage: yGxGz = faces[(1, -1, 1)] # closed face y >= x >= z + sage: xGyGz = faces[(1, 1, 1)] # closed face x >= y >= z + sage: a.face_product(xGyEz, yGxGz) == xGyGz True - sage: a.face_product(yGxGz, xGyEz) == yGxGz # optional - sage.graphs + sage: a.face_product(yGxGz, xGyEz) == yGxGz True - sage: xEzGy = faces[(-1, 1, 0)] # closed face x = z >= y # optional - sage.graphs - sage: xGzGy = faces[(-1, 1, 1)] # closed face x >= z >= y # optional - sage.graphs - sage: a.face_product(xEzGy, yGxGz) == xGzGy # optional - sage.graphs + sage: xEzGy = faces[(-1, 1, 0)] # closed face x = z >= y + sage: xGzGy = faces[(-1, 1, 1)] # closed face x >= z >= y + sage: a.face_product(xEzGy, yGxGz) == xGzGy True """ f = F.representative_point() @@ -2433,8 +2452,9 @@ def face_semigroup_algebra(self, field=None, names='e'): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: [(i, F[0]) for i, F in enumerate(a.closed_faces())] # optional - sage.graphs + sage: # needs sage.graphs + sage: a = hyperplane_arrangements.braid(3) + sage: [(i, F[0]) for i, F in enumerate(a.closed_faces())] [(0, (0, 0, 0)), (1, (0, 1, 1)), (2, (0, -1, -1)), @@ -2448,44 +2468,45 @@ def face_semigroup_algebra(self, field=None, names='e'): (10, (-1, 1, 1)), (11, (-1, 1, -1)), (12, (-1, -1, -1))] - sage: U = a.face_semigroup_algebra(); U # optional - sage.graphs + sage: U = a.face_semigroup_algebra(); U Finite-dimensional algebra of degree 13 over Rational Field - sage: e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12 = U.basis() # optional - sage.graphs - sage: e0 * e1 # optional - sage.graphs + sage: e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12 = U.basis() + sage: e0 * e1 e1 - sage: e0 * e5 # optional - sage.graphs + sage: e0 * e5 e5 - sage: e5 * e0 # optional - sage.graphs + sage: e5 * e0 e5 - sage: e3 * e2 # optional - sage.graphs + sage: e3 * e2 e6 - sage: e7 * e12 # optional - sage.graphs + sage: e7 * e12 e7 - sage: e3 * e12 # optional - sage.graphs + sage: e3 * e12 e6 - sage: e4 * e8 # optional - sage.graphs + sage: e4 * e8 e4 - sage: e8 * e4 # optional - sage.graphs + sage: e8 * e4 e11 - sage: e8 * e1 # optional - sage.graphs + sage: e8 * e1 e11 - sage: e5 * e12 # optional - sage.graphs + sage: e5 * e12 e7 - sage: (e3 + 2*e4) * (e1 - e7) # optional - sage.graphs + sage: (e3 + 2*e4) * (e1 - e7) e4 - e6 - sage: U3 = a.face_semigroup_algebra(field=GF(3)); U3 # optional - sage.graphs sage.rings.finite_rings + sage: U3 = a.face_semigroup_algebra(field=GF(3)); U3 # needs sage.graphs sage.rings.finite_rings Finite-dimensional algebra of degree 13 over Finite Field of size 3 TESTS: The ``names`` keyword works:: - sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs - sage: U = a.face_semigroup_algebra(names='x'); U # optional - sage.graphs + sage: # needs sage.graphs + sage: a = hyperplane_arrangements.braid(3) + sage: U = a.face_semigroup_algebra(names='x'); U Finite-dimensional algebra of degree 13 over Rational Field - sage: e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12 = U.basis() # optional - sage.graphs - sage: e0 * e1 # optional - sage.graphs + sage: e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12 = U.basis() + sage: e0 * e1 x1 """ if field is None: @@ -2545,8 +2566,8 @@ def region_containing_point(self, p): TESTS:: sage: A = H([(1,1),0], [(2,3),-1], [(4,5),3]) - sage: B = A.change_ring(FiniteField(7)) # optional - sage.rings.finite_rings - sage: B.region_containing_point((1,2)) # optional - sage.rings.finite_rings + sage: B = A.change_ring(FiniteField(7)) + sage: B.region_containing_point((1,2)) Traceback (most recent call last): ... ValueError: base field must have characteristic zero @@ -2584,8 +2605,8 @@ def _bounded_region_indices(self): EXAMPLES:: - sage: a = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: a._bounded_region_indices() # optional - sage.combinat + sage: a = hyperplane_arrangements.semiorder(3) + sage: a._bounded_region_indices() (2, 7, 8, 9, 10, 11, 16) """ from sage.geometry.polyhedron.constructor import Polyhedron @@ -2620,8 +2641,9 @@ def bounded_regions(self): EXAMPLES:: - sage: A = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: A.bounded_regions() # optional - sage.combinat + sage: # needs sage.combinat + sage: A = hyperplane_arrangements.semiorder(3) + sage: A.bounded_regions() (A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices and 1 line, A 3-dimensional polyhedron in QQ^3 defined @@ -2636,9 +2658,9 @@ def bounded_regions(self): as the convex hull of 3 vertices and 1 line, A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 3 vertices and 1 line) - sage: A.bounded_regions()[0].is_compact() # the regions are only *relatively* bounded # optional - sage.combinat + sage: A.bounded_regions()[0].is_compact() # the regions are only *relatively* bounded False - sage: A.is_essential() # optional - sage.combinat + sage: A.is_essential() False """ return tuple(self.regions()[i] for i in self._bounded_region_indices()) @@ -2659,11 +2681,12 @@ def unbounded_regions(self): EXAMPLES:: - sage: A = hyperplane_arrangements.semiorder(3) # optional - sage.combinat - sage: B = A.essentialization() # optional - sage.combinat - sage: B.n_regions() - B.n_bounded_regions() # optional - sage.combinat + sage: # needs sage.combinat + sage: A = hyperplane_arrangements.semiorder(3) + sage: B = A.essentialization() + sage: B.n_regions() - B.n_bounded_regions() 12 - sage: B.unbounded_regions() # optional - sage.combinat + sage: B.unbounded_regions() (A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices and 1 ray, A 2-dimensional polyhedron in QQ^2 defined @@ -2711,8 +2734,8 @@ def whitney_data(self): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat - sage: A.whitney_data() # optional - sage.combinat + sage: A = hyperplane_arrangements.Shi(3) + sage: A.whitney_data() # needs sage.combinat ( [ 1 -6 9] [ 1 6 6] [ 0 6 -15] [ 0 6 15] @@ -2761,12 +2784,13 @@ def doubly_indexed_whitney_number(self, i, j, kind=1): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat - sage: A.doubly_indexed_whitney_number(0, 2) # optional - sage.combinat + sage: # needs sage.combinat + sage: A = hyperplane_arrangements.Shi(3) + sage: A.doubly_indexed_whitney_number(0, 2) 9 - sage: A.whitney_number(2) # optional - sage.combinat + sage: A.whitney_number(2) 9 - sage: A.doubly_indexed_whitney_number(1, 2) # optional - sage.combinat + sage: A.doubly_indexed_whitney_number(1, 2) -15 REFERENCES: @@ -2811,20 +2835,21 @@ def whitney_number(self, k, kind=1): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat - sage: A.whitney_number(0) # optional - sage.combinat + sage: # needs sage.combinat + sage: A = hyperplane_arrangements.Shi(3) + sage: A.whitney_number(0) 1 - sage: A.whitney_number(1) # optional - sage.combinat + sage: A.whitney_number(1) -6 - sage: A.whitney_number(2) # optional - sage.combinat + sage: A.whitney_number(2) 9 - sage: A.characteristic_polynomial() # optional - sage.combinat + sage: A.characteristic_polynomial() x^3 - 6*x^2 + 9*x - sage: A.whitney_number(1, kind=2) # optional - sage.combinat + sage: A.whitney_number(1, kind=2) 6 - sage: p = A.intersection_poset() # optional - sage.combinat - sage: r = p.rank_function() # optional - sage.combinat - sage: len([i for i in p if r(i) == 1]) # optional - sage.combinat + sage: p = A.intersection_poset() + sage: r = p.rank_function() + sage: len([i for i in p if r(i) == 1]) 6 """ if k >= 0 and k <= self.dimension(): @@ -3005,8 +3030,8 @@ def matroid(self): intersection lattice:: sage: f = sum([list(M.flats(i)) for i in range(M.rank() + 1)], []) - sage: PF = Poset([f, lambda x, y: x < y]) # optional - sage.combinat - sage: PF.is_isomorphic(A.intersection_poset()) # optional - sage.combinat + sage: PF = Poset([f, lambda x, y: x < y]) # needs sage.combinat + sage: PF.is_isomorphic(A.intersection_poset()) # needs sage.combinat True """ if not self.is_central(): @@ -3096,13 +3121,14 @@ def minimal_generated_number(self): Check that :trac:`26705` is fixed:: - sage: w = WeylGroup(['A', 4]).from_reduced_word([3, 4, 2, 1]) # optional - sage.combinat sage.groups - sage: I = w.inversion_arrangement() # optional - sage.combinat sage.groups - sage: I # optional - sage.combinat sage.groups + sage: # needs sage.combinat sage.groups + sage: w = WeylGroup(['A', 4]).from_reduced_word([3, 4, 2, 1]) + sage: I = w.inversion_arrangement() + sage: I Arrangement - sage: I.minimal_generated_number() # optional - sage.combinat sage.groups + sage: I.minimal_generated_number() 0 - sage: I.is_formal() # optional - sage.combinat sage.groups + sage: I.is_formal() True """ V = VectorSpace(self.base_ring(), self.dimension()) @@ -3184,9 +3210,9 @@ def derivation_module_free_chain(self): EXAMPLES:: - sage: W = WeylGroup(['A',3], prefix='s') # optional - sage.combinat sage.groups - sage: A = W.long_element().inversion_arrangement() # optional - sage.combinat sage.groups - sage: for M in A.derivation_module_free_chain(): print("%s\n"%M) # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A',3], prefix='s') # needs sage.combinat sage.groups + sage: A = W.long_element().inversion_arrangement() # needs sage.combinat sage.groups + sage: for M in A.derivation_module_free_chain(): print("%s\n"%M) # needs sage.combinat sage.groups [ 1 0 0] [ 0 1 0] [ 0 0 a3] @@ -3260,8 +3286,8 @@ def is_free(self, algorithm="singular"): For type `A` arrangements, chordality is equivalent to freeness. We verify that in type `A_3`:: - sage: W = WeylGroup(['A', 3], prefix='s') # optional - sage.combinat sage.groups - sage: for x in W: # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 3], prefix='s') # needs sage.combinat sage.groups + sage: for x in W: # needs sage.combinat sage.groups ....: A = x.inversion_arrangement() ....: assert A.matroid().is_chordal() == A.is_free() @@ -3269,8 +3295,8 @@ def is_free(self, algorithm="singular"): We check that the algorithms agree:: - sage: W = WeylGroup(['B', 3], prefix='s') # optional - sage.combinat sage.groups - sage: for x in W: # long time # optional - sage.combinat sage.groups + sage: W = WeylGroup(['B', 3], prefix='s') # needs sage.combinat sage.groups + sage: for x in W: # long time # needs sage.combinat sage.groups ....: A = x.inversion_arrangement() ....: assert (A.is_free(algorithm="BC") ....: == A.is_free(algorithm="singular")) @@ -3329,19 +3355,19 @@ def derivation_module_basis(self, algorithm="singular"): EXAMPLES:: - sage: W = WeylGroup(['A', 2], prefix='s') # optional - sage.combinat sage.groups - sage: A = W.long_element().inversion_arrangement() # optional - sage.combinat sage.groups - sage: A.derivation_module_basis() # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 2], prefix='s') # needs sage.combinat sage.groups + sage: A = W.long_element().inversion_arrangement() # needs sage.combinat sage.groups + sage: A.derivation_module_basis() # needs sage.combinat sage.groups [(a1, a2), (0, a1*a2 + a2^2)] TESTS: We check the algorithms produce a basis with the same exponents:: - sage: W = WeylGroup(['A', 2], prefix='s') # optional - sage.combinat sage.groups - sage: def exponents(B): # optional - sage.combinat sage.groups + sage: W = WeylGroup(['A', 2], prefix='s') # needs sage.combinat sage.groups + sage: def exponents(B): ....: return sorted([max(x.degree() for x in b) for b in B]) - sage: for x in W: # long time # optional - sage.combinat sage.groups + sage: for x in W: # long time # needs sage.combinat sage.groups ....: A = x.inversion_arrangement() ....: B = A.derivation_module_basis(algorithm="singular") ....: Bp = A.derivation_module_basis(algorithm="BC") @@ -3633,7 +3659,8 @@ def ngens(self): EXAMPLES:: sage: L. = HyperplaneArrangements(QQ); L - Hyperplane arrangements in 3-dimensional linear space over Rational Field with coordinates x, y, z + Hyperplane arrangements in 3-dimensional linear space + over Rational Field with coordinates x, y, z sage: L.ngens() 3 """ diff --git a/src/sage/geometry/hyperplane_arrangement/hyperplane.py b/src/sage/geometry/hyperplane_arrangement/hyperplane.py index 8284022d3d8..8d4b301f8d8 100644 --- a/src/sage/geometry/hyperplane_arrangement/hyperplane.py +++ b/src/sage/geometry/hyperplane_arrangement/hyperplane.py @@ -26,7 +26,7 @@ (3, 2, -5) sage: h.constant_term() -7 - sage: h.change_ring(GF(3)) # optional - sage.rings.finite_rings + sage: h.change_ring(GF(3)) Hyperplane 0*x + 2*y + z + 2 sage: h.point() (21/38, 7/19, -35/38) @@ -238,9 +238,9 @@ def _normal_pivot(self): sage: (x + 3/2*y - 2*z)._normal_pivot() 2 - sage: H. = HyperplaneArrangements(GF(5)) # optional - sage.rings.finite_rings - sage: V = H.ambient_space() # optional - sage.rings.finite_rings - sage: (x + 3*y - 4*z)._normal_pivot() # optional - sage.rings.finite_rings + sage: H. = HyperplaneArrangements(GF(5)) + sage: V = H.ambient_space() + sage: (x + 3*y - 4*z)._normal_pivot() 1 """ try: @@ -397,16 +397,17 @@ def point(self): sage: h.point() in h True - sage: H. = HyperplaneArrangements(GF(3)) # optional - sage.rings.finite_rings - sage: h = 2*x + y + z + 1 # optional - sage.rings.finite_rings - sage: h.point() # optional - sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: H. = HyperplaneArrangements(GF(3)) + sage: h = 2*x + y + z + 1 + sage: h.point() (1, 0, 0) - sage: h.point().base_ring() # optional - sage.rings.finite_rings + sage: h.point().base_ring() Finite Field of size 3 - sage: H. = HyperplaneArrangements(GF(3)) # optional - sage.rings.finite_rings - sage: h = x + y + z + 1 # optional - sage.rings.finite_rings - sage: h.point() # optional - sage.rings.finite_rings + sage: H. = HyperplaneArrangements(GF(3)) + sage: h = x + y + z + 1 + sage: h.point() (2, 0, 0) """ P = self.parent() @@ -552,21 +553,23 @@ def primitive(self, signed=True): Check that :trac:`30078` is fixed:: - sage: R. = QuadraticField(2) # optional - sage.rings.number_field - sage: H. = HyperplaneArrangements(base_ring=R) # optional - sage.rings.number_field - sage: B = H([1,1,0], [2,2,0], [sqrt2,sqrt2,0]) # optional - sage.rings.number_field - sage: B # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: R. = QuadraticField(2) + sage: H. = HyperplaneArrangements(base_ring=R) + sage: B = H([1,1,0], [2,2,0], [sqrt2,sqrt2,0]) + sage: B Arrangement Check that :trac:`30749` is fixed:: - sage: tau = (1+AA(5).sqrt()) / 2 # optional - sage.rings.number_field - sage: ncn = [[2*tau+1,2*tau,tau],[2*tau+2,2*tau+1,tau+1]] # optional - sage.rings.number_field - sage: ncn += [[tau+1,tau+1,tau],[2*tau,2*tau,tau],[tau+1,tau+1,1]] # optional - sage.rings.number_field - sage: ncn += [[1,1,1],[1,1,0],[0,1,0],[1,0,0],[tau+1,tau,tau]] # optional - sage.rings.number_field - sage: H = HyperplaneArrangements(AA,names='xyz') # optional - sage.rings.number_field - sage: A = H([[0]+v for v in ncn]) # optional - sage.rings.number_field - sage: A.n_regions() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: tau = (1+AA(5).sqrt()) / 2 + sage: ncn = [[2*tau+1,2*tau,tau],[2*tau+2,2*tau+1,tau+1]] + sage: ncn += [[tau+1,tau+1,tau],[2*tau,2*tau,tau],[tau+1,tau+1,1]] + sage: ncn += [[1,1,1],[1,1,0],[0,1,0],[1,0,0],[tau+1,tau,tau]] + sage: H = HyperplaneArrangements(AA,names='xyz') + sage: A = H([[0]+v for v in ncn]) + sage: A.n_regions() 60 """ from sage.rings.rational_field import QQ @@ -638,7 +641,7 @@ def plot(self, **kwds): EXAMPLES:: sage: L. = HyperplaneArrangements(QQ) - sage: (x + y - 2).plot() # optional - sage.plot + sage: (x + y - 2).plot() # needs sage.plot Graphics object consisting of 2 graphics primitives """ from sage.geometry.hyperplane_arrangement.plot import plot_hyperplane diff --git a/src/sage/geometry/hyperplane_arrangement/library.py b/src/sage/geometry/hyperplane_arrangement/library.py index 5d0b4aae4d7..83c4f80c325 100644 --- a/src/sage/geometry/hyperplane_arrangement/library.py +++ b/src/sage/geometry/hyperplane_arrangement/library.py @@ -90,7 +90,7 @@ def braid(self, n, K=QQ, names=None): EXAMPLES:: - sage: hyperplane_arrangements.braid(4) # optional - sage.graphs + sage: hyperplane_arrangements.braid(4) # needs sage.graphs Arrangement of 6 hyperplanes of dimension 4 and rank 3 """ x = polygen(QQ, 'x') @@ -124,18 +124,19 @@ def bigraphical(self, G, A=None, K=QQ, names=None): EXAMPLES:: - sage: G = graphs.CycleGraph(4) # optional - sage.graphs - sage: G.edges(sort=True) # optional - sage.graphs + sage: # needs sage.graphs + sage: G = graphs.CycleGraph(4) + sage: G.edges(sort=True) [(0, 1, None), (0, 3, None), (1, 2, None), (2, 3, None)] - sage: G.edges(sort=True, labels=False) # optional - sage.graphs + sage: G.edges(sort=True, labels=False) [(0, 1), (0, 3), (1, 2), (2, 3)] - sage: A = {0:{1:1, 3:2}, 1:{0:3, 2:0}, 2:{1:2, 3:1}, 3:{2:0, 0:2}} # optional - sage.graphs - sage: HA = hyperplane_arrangements.bigraphical(G, A) # optional - sage.graphs - sage: HA.n_regions() # optional - sage.graphs + sage: A = {0:{1:1, 3:2}, 1:{0:3, 2:0}, 2:{1:2, 3:1}, 3:{2:0, 0:2}} + sage: HA = hyperplane_arrangements.bigraphical(G, A) + sage: HA.n_regions() 63 - sage: hyperplane_arrangements.bigraphical(G, 'generic').n_regions() # optional - sage.graphs + sage: hyperplane_arrangements.bigraphical(G, 'generic').n_regions() 65 - sage: hyperplane_arrangements.bigraphical(G).n_regions() # optional - sage.graphs + sage: hyperplane_arrangements.bigraphical(G).n_regions() 59 REFERENCES: @@ -253,11 +254,12 @@ def G_semiorder(self, G, K=QQ, names=None): EXAMPLES:: - sage: G = graphs.CompleteGraph(5) # optional - sage.graphs - sage: hyperplane_arrangements.G_semiorder(G) # optional - sage.graphs + sage: # needs sage.graphs + sage: G = graphs.CompleteGraph(5) + sage: hyperplane_arrangements.G_semiorder(G) Arrangement of 20 hyperplanes of dimension 5 and rank 4 - sage: g = graphs.HouseGraph() # optional - sage.graphs - sage: hyperplane_arrangements.G_semiorder(g) # optional - sage.graphs + sage: g = graphs.HouseGraph() + sage: hyperplane_arrangements.G_semiorder(g) Arrangement of 12 hyperplanes of dimension 5 and rank 4 """ n = G.num_verts() @@ -291,13 +293,14 @@ def G_Shi(self, G, K=QQ, names=None): EXAMPLES:: - sage: G = graphs.CompleteGraph(5) # optional - sage.graphs - sage: hyperplane_arrangements.G_Shi(G) # optional - sage.graphs + sage: # needs sage.graphs + sage: G = graphs.CompleteGraph(5) + sage: hyperplane_arrangements.G_Shi(G) Arrangement of 20 hyperplanes of dimension 5 and rank 4 - sage: g = graphs.HouseGraph() # optional - sage.graphs - sage: hyperplane_arrangements.G_Shi(g) # optional - sage.graphs + sage: g = graphs.HouseGraph() + sage: hyperplane_arrangements.G_Shi(g) Arrangement of 12 hyperplanes of dimension 5 and rank 4 - sage: a = hyperplane_arrangements.G_Shi(graphs.WheelGraph(4)); a # optional - sage.graphs + sage: a = hyperplane_arrangements.G_Shi(graphs.WheelGraph(4)); a Arrangement of 12 hyperplanes of dimension 4 and rank 3 """ n = G.num_verts() @@ -333,20 +336,22 @@ def graphical(self, G, K=QQ, names=None): EXAMPLES:: - sage: G = graphs.CompleteGraph(5) # optional - sage.graphs - sage: hyperplane_arrangements.graphical(G) # optional - sage.graphs + sage: # needs sage.graphs + sage: G = graphs.CompleteGraph(5) + sage: hyperplane_arrangements.graphical(G) Arrangement of 10 hyperplanes of dimension 5 and rank 4 - sage: g = graphs.HouseGraph() # optional - sage.graphs - sage: hyperplane_arrangements.graphical(g) # optional - sage.graphs + sage: g = graphs.HouseGraph() + sage: hyperplane_arrangements.graphical(g) Arrangement of 6 hyperplanes of dimension 5 and rank 4 TESTS:: - sage: h = hyperplane_arrangements.graphical(g) # optional - sage.graphs - sage: h.characteristic_polynomial() # optional - sage.graphs + sage: # needs sage.graphs + sage: h = hyperplane_arrangements.graphical(g) + sage: h.characteristic_polynomial() x^5 - 6*x^4 + 14*x^3 - 15*x^2 + 6*x - sage: h.characteristic_polynomial.clear_cache() # long time # optional - sage.graphs - sage: h.characteristic_polynomial() # long time # optional - sage.graphs + sage: h.characteristic_polynomial.clear_cache() # long time + sage: h.characteristic_polynomial() # long time x^5 - 6*x^4 + 14*x^3 - 15*x^2 + 6*x """ n = G.num_verts() @@ -388,18 +393,19 @@ def Ish(self, n, K=QQ, names=None): EXAMPLES:: - sage: a = hyperplane_arrangements.Ish(3); a # optional - sage.combinat + sage: # needs sage.combinat + sage: a = hyperplane_arrangements.Ish(3); a Arrangement of 6 hyperplanes of dimension 3 and rank 2 - sage: a.characteristic_polynomial() # optional - sage.combinat + sage: a.characteristic_polynomial() x^3 - 6*x^2 + 9*x - sage: b = hyperplane_arrangements.Shi(3) # optional - sage.combinat - sage: b.characteristic_polynomial() # optional - sage.combinat + sage: b = hyperplane_arrangements.Shi(3) + sage: b.characteristic_polynomial() x^3 - 6*x^2 + 9*x TESTS:: - sage: a.characteristic_polynomial.clear_cache() # long time # optional - sage.combinat - sage: a.characteristic_polynomial() # long time # optional - sage.combinat + sage: a.characteristic_polynomial.clear_cache() # long time # needs sage.combinat + sage: a.characteristic_polynomial() # long time # needs sage.combinat x^3 - 6*x^2 + 9*x REFERENCES: @@ -565,16 +571,17 @@ def semiorder(self, n, K=QQ, names=None): EXAMPLES:: - sage: hyperplane_arrangements.semiorder(4) # optional - sage.combinat + sage: hyperplane_arrangements.semiorder(4) Arrangement of 12 hyperplanes of dimension 4 and rank 3 TESTS:: - sage: h = hyperplane_arrangements.semiorder(5) # optional - sage.combinat - sage: h.characteristic_polynomial() # optional - sage.combinat + sage: # needs sage.combinat + sage: h = hyperplane_arrangements.semiorder(5) + sage: h.characteristic_polynomial() x^5 - 20*x^4 + 180*x^3 - 790*x^2 + 1380*x - sage: h.characteristic_polynomial.clear_cache() # long time # optional - sage.combinat - sage: h.characteristic_polynomial() # long time # optional - sage.combinat + sage: h.characteristic_polynomial.clear_cache() # long time + sage: h.characteristic_polynomial() # long time x^5 - 20*x^4 + 180*x^3 - 790*x^2 + 1380*x """ H = make_parent(K, n, names) @@ -626,29 +633,30 @@ def Shi(self, data, K=QQ, names=None, m=1): EXAMPLES:: - sage: hyperplane_arrangements.Shi(4) # optional - sage.combinat + sage: # needs sage.combinat + sage: hyperplane_arrangements.Shi(4) Arrangement of 12 hyperplanes of dimension 4 and rank 3 - sage: hyperplane_arrangements.Shi("A3") # optional - sage.combinat + sage: hyperplane_arrangements.Shi("A3") Arrangement of 12 hyperplanes of dimension 4 and rank 3 - sage: hyperplane_arrangements.Shi("A3", m=2) # optional - sage.combinat + sage: hyperplane_arrangements.Shi("A3", m=2) Arrangement of 24 hyperplanes of dimension 4 and rank 3 - sage: hyperplane_arrangements.Shi("B4") # optional - sage.combinat + sage: hyperplane_arrangements.Shi("B4") Arrangement of 32 hyperplanes of dimension 4 and rank 4 - sage: hyperplane_arrangements.Shi("B4", m=3) # optional - sage.combinat + sage: hyperplane_arrangements.Shi("B4", m=3) Arrangement of 96 hyperplanes of dimension 4 and rank 4 - sage: hyperplane_arrangements.Shi("C3") # optional - sage.combinat + sage: hyperplane_arrangements.Shi("C3") Arrangement of 18 hyperplanes of dimension 3 and rank 3 - sage: hyperplane_arrangements.Shi("D4", m=3) # optional - sage.combinat + sage: hyperplane_arrangements.Shi("D4", m=3) Arrangement of 72 hyperplanes of dimension 4 and rank 4 - sage: hyperplane_arrangements.Shi("E6") # optional - sage.combinat + sage: hyperplane_arrangements.Shi("E6") Arrangement of 72 hyperplanes of dimension 8 and rank 6 - sage: hyperplane_arrangements.Shi("E6", m=2) # optional - sage.combinat + sage: hyperplane_arrangements.Shi("E6", m=2) Arrangement of 144 hyperplanes of dimension 8 and rank 6 If the Cartan type is not crystallographic, the Shi arrangement is not defined:: - sage: hyperplane_arrangements.Shi("H4") # optional - sage.combinat + sage: hyperplane_arrangements.Shi("H4") Traceback (most recent call last): ... NotImplementedError: Shi arrangements are not defined for non crystallographic Cartan types @@ -656,36 +664,38 @@ def Shi(self, data, K=QQ, names=None, m=1): The characteristic polynomial is pre-computed using the results of [Ath1996]_:: - sage: hyperplane_arrangements.Shi("A3").characteristic_polynomial() # optional - sage.combinat + sage: # needs sage.combinat + sage: hyperplane_arrangements.Shi("A3").characteristic_polynomial() x^4 - 12*x^3 + 48*x^2 - 64*x - sage: hyperplane_arrangements.Shi("A3", m=2).characteristic_polynomial() # optional - sage.combinat + sage: hyperplane_arrangements.Shi("A3", m=2).characteristic_polynomial() x^4 - 24*x^3 + 192*x^2 - 512*x - sage: hyperplane_arrangements.Shi("C3").characteristic_polynomial() # optional - sage.combinat + sage: hyperplane_arrangements.Shi("C3").characteristic_polynomial() x^3 - 18*x^2 + 108*x - 216 - sage: hyperplane_arrangements.Shi("E6").characteristic_polynomial() # optional - sage.combinat + sage: hyperplane_arrangements.Shi("E6").characteristic_polynomial() x^8 - 72*x^7 + 2160*x^6 - 34560*x^5 + 311040*x^4 - 1492992*x^3 + 2985984*x^2 - sage: hyperplane_arrangements.Shi("B4", m=3).characteristic_polynomial() # optional - sage.combinat + sage: hyperplane_arrangements.Shi("B4", m=3).characteristic_polynomial() x^4 - 96*x^3 + 3456*x^2 - 55296*x + 331776 TESTS:: - sage: h = hyperplane_arrangements.Shi(4) # optional - sage.combinat - sage: h.characteristic_polynomial() # optional - sage.combinat + sage: # needs sage.combinat + sage: h = hyperplane_arrangements.Shi(4) + sage: h.characteristic_polynomial() x^4 - 12*x^3 + 48*x^2 - 64*x - sage: h.characteristic_polynomial.clear_cache() # long time # optional - sage.combinat - sage: h.characteristic_polynomial() # long time # optional - sage.combinat + sage: h.characteristic_polynomial.clear_cache() # long time + sage: h.characteristic_polynomial() # long time x^4 - 12*x^3 + 48*x^2 - 64*x - sage: h = hyperplane_arrangements.Shi("A3", m=2) # optional - sage.combinat - sage: h.characteristic_polynomial() # optional - sage.combinat + sage: h = hyperplane_arrangements.Shi("A3", m=2) + sage: h.characteristic_polynomial() x^4 - 24*x^3 + 192*x^2 - 512*x - sage: h.characteristic_polynomial.clear_cache() # optional - sage.combinat - sage: h.characteristic_polynomial() # optional - sage.combinat + sage: h.characteristic_polynomial.clear_cache() + sage: h.characteristic_polynomial() x^4 - 24*x^3 + 192*x^2 - 512*x - sage: h = hyperplane_arrangements.Shi("B3", m=3) # optional - sage.combinat - sage: h.characteristic_polynomial() # optional - sage.combinat + sage: h = hyperplane_arrangements.Shi("B3", m=3) + sage: h.characteristic_polynomial() x^3 - 54*x^2 + 972*x - 5832 - sage: h.characteristic_polynomial.clear_cache() # optional - sage.combinat - sage: h.characteristic_polynomial() # optional - sage.combinat + sage: h.characteristic_polynomial.clear_cache() + sage: h.characteristic_polynomial() x^3 - 54*x^2 + 972*x - 5832 """ if data in NN: diff --git a/src/sage/geometry/hyperplane_arrangement/plot.py b/src/sage/geometry/hyperplane_arrangement/plot.py index d2c62f2d547..be468c111bc 100644 --- a/src/sage/geometry/hyperplane_arrangement/plot.py +++ b/src/sage/geometry/hyperplane_arrangement/plot.py @@ -56,26 +56,26 @@ sage: H3. = HyperplaneArrangements(QQ) sage: A = H3([(1,0,0), 0], [(0,0,1), 5]) - sage: A.plot(hyperplane_opacities=0.5, hyperplane_labels=True, # optional - sage.plot + sage: A.plot(hyperplane_opacities=0.5, hyperplane_labels=True, # needs sage.plot ....: hyperplane_legend=False) Graphics3d Object sage: c = H3([(1,0,0),0], [(0,0,1),5]) - sage: c.plot(ranges=10) # optional - sage.plot + sage: c.plot(ranges=10) # needs sage.plot Graphics3d Object - sage: c.plot(ranges=[[9.5,10], [-3,3]]) # optional - sage.plot + sage: c.plot(ranges=[[9.5,10], [-3,3]]) # needs sage.plot Graphics3d Object - sage: c.plot(ranges=[[[9.5,10], [-3,3]], [[-6,6], [-5,5]]]) # optional - sage.plot + sage: c.plot(ranges=[[[9.5,10], [-3,3]], [[-6,6], [-5,5]]]) # needs sage.plot Graphics3d Object sage: H2. = HyperplaneArrangements(QQ) sage: h = H2([(1,1),0], [(1,-1),0], [(0,1),2]) - sage: h.plot(ranges=20) # optional - sage.plot + sage: h.plot(ranges=20) # needs sage.plot Graphics object consisting of 3 graphics primitives - sage: h.plot(ranges=[-1, 10]) # optional - sage.plot + sage: h.plot(ranges=[-1, 10]) # needs sage.plot Graphics object consisting of 3 graphics primitives - sage: h.plot(ranges=[[-1, 1], [-5, 5], [-1, 10]]) # optional - sage.plot + sage: h.plot(ranges=[[-1, 1], [-5, 5], [-1, 10]]) # needs sage.plot Graphics object consisting of 3 graphics primitives sage: a = hyperplane_arrangements.coordinate(3) @@ -84,24 +84,24 @@ sage: opts['label_offsets'] = [(0,2,2), (2,0,2), (2,2,0)] sage: opts['hyperplane_legend'] = False sage: opts['hyperplane_opacities'] = 0.7 - sage: a.plot(**opts) # optional - sage.plot + sage: a.plot(**opts) # needs sage.plot Graphics3d Object sage: opts['hyperplane_labels'] = 'short' - sage: a.plot(**opts) # optional - sage.plot + sage: a.plot(**opts) # needs sage.plot Graphics3d Object sage: H. = HyperplaneArrangements(QQ) sage: pts = H(3*u+4, 2*u+5, 7*u+1) - sage: pts.plot(hyperplane_colors=['yellow','black','blue']) # optional - sage.plot + sage: pts.plot(hyperplane_colors=['yellow','black','blue']) # needs sage.plot Graphics object consisting of 3 graphics primitives - sage: pts.plot(point_sizes=[50,100,200], hyperplane_colors='blue') # optional - sage.plot + sage: pts.plot(point_sizes=[50,100,200], hyperplane_colors='blue') # needs sage.plot Graphics object consisting of 3 graphics primitives sage: H. = HyperplaneArrangements(QQ) sage: a = H(x, y+1, y+2) - sage: a.plot(hyperplane_labels=True, label_colors='blue', label_fontsize=18) # optional - sage.plot + sage: a.plot(hyperplane_labels=True, label_colors='blue', label_fontsize=18) # needs sage.plot Graphics3d Object - sage: a.plot(hyperplane_labels=True, label_colors=['red','green','black']) # optional - sage.plot + sage: a.plot(hyperplane_labels=True, label_colors=['red','green','black']) # needs sage.plot Graphics3d Object """ from copy import copy @@ -145,8 +145,8 @@ def plot(hyperplane_arrangement, **kwds): EXAMPLES:: - sage: B = hyperplane_arrangements.semiorder(4) # optional - sage.combinat - sage: B.plot() # optional - sage.combinat sage.plot + sage: B = hyperplane_arrangements.semiorder(4) + sage: B.plot() # needs sage.combinat sage.plot Displaying the essentialization. Graphics3d Object """ @@ -331,34 +331,35 @@ def plot_hyperplane(hyperplane, **kwds): sage: H1. = HyperplaneArrangements(QQ) sage: a = 3*x + 4 - sage: a.plot() # indirect doctest # optional - sage.plot + sage: a.plot() # indirect doctest # needs sage.plot Graphics object consisting of 3 graphics primitives - sage: a.plot(point_size=100, hyperplane_label='hello') # optional - sage.plot + sage: a.plot(point_size=100, hyperplane_label='hello') # needs sage.plot Graphics object consisting of 3 graphics primitives sage: H2. = HyperplaneArrangements(QQ) sage: b = 3*x + 4*y + 5 - sage: b.plot() # optional - sage.plot + sage: b.plot() # needs sage.plot Graphics object consisting of 2 graphics primitives - sage: b.plot(ranges=(1,5), label_offset=(2,-1)) # optional - sage.plot + sage: b.plot(ranges=(1,5), label_offset=(2,-1)) # needs sage.plot Graphics object consisting of 2 graphics primitives sage: opts = {'hyperplane_label': True, 'label_color': 'green', ....: 'label_fontsize': 24, 'label_offset': (0,1.5)} - sage: b.plot(**opts) # optional - sage.plot + sage: b.plot(**opts) # needs sage.plot Graphics object consisting of 2 graphics primitives + sage: # needs sage.plot sage: H3. = HyperplaneArrangements(QQ) sage: c = 2*x + 3*y + 4*z + 5 - sage: c.plot() # optional - sage.plot + sage: c.plot() Graphics3d Object - sage: c.plot(label_offset=(1,0,1), color='green', label_color='red', # optional - sage.plot + sage: c.plot(label_offset=(1,0,1), color='green', label_color='red', ....: frame=False) Graphics3d Object sage: d = -3*x + 2*y + 2*z + 3 - sage: d.plot(opacity=0.8) # optional - sage.plot + sage: d.plot(opacity=0.8) Graphics3d Object sage: e = 4*x + 2*z + 3 - sage: e.plot(ranges=[[-1,1],[0,8]], label_offset=(2,2,1), aspect_ratio=1) # optional - sage.plot + sage: e.plot(ranges=[[-1,1],[0,8]], label_offset=(2,2,1), aspect_ratio=1) Graphics3d Object """ if hyperplane.base_ring().characteristic(): @@ -486,22 +487,22 @@ def legend_3d(hyperplane_arrangement, hyperplane_colors, length): EXAMPLES:: - sage: a = hyperplane_arrangements.semiorder(3) # optional - sage.combinat + sage: a = hyperplane_arrangements.semiorder(3) sage: from sage.geometry.hyperplane_arrangement.plot import legend_3d - sage: legend_3d(a, list(colors.values())[:6], length='long') # optional - sage.combinat sage.plot + sage: legend_3d(a, list(colors.values())[:6], length='long') # needs sage.combinat sage.plot Graphics object consisting of 6 graphics primitives - sage: b = hyperplane_arrangements.semiorder(4) # optional - sage.combinat - sage: c = b.essentialization() # optional - sage.combinat - sage: legend_3d(c, list(colors.values())[:12], length='long') # optional - sage.combinat sage.plot + sage: b = hyperplane_arrangements.semiorder(4) + sage: c = b.essentialization() + sage: legend_3d(c, list(colors.values())[:12], length='long') # needs sage.combinat sage.plot Graphics object consisting of 12 graphics primitives - sage: legend_3d(c, list(colors.values())[:12], length='short') # optional - sage.combinat sage.plot + sage: legend_3d(c, list(colors.values())[:12], length='short') # needs sage.combinat sage.plot Graphics object consisting of 12 graphics primitives - sage: p = legend_3d(c, list(colors.values())[:12], length='short') # optional - sage.combinat sage.plot - sage: p.set_legend_options(ncol=4) # optional - sage.combinat sage.plot - sage: type(p) # optional - sage.combinat sage.plot + sage: p = legend_3d(c, list(colors.values())[:12], length='short') # needs sage.combinat sage.plot + sage: p.set_legend_options(ncol=4) # needs sage.combinat sage.plot + sage: type(p) # needs sage.combinat sage.plot """ if hyperplane_arrangement.dimension() != 3: diff --git a/src/sage/geometry/integral_points.pxi b/src/sage/geometry/integral_points.pxi index dae34bc99af..c45f7f1cb2e 100644 --- a/src/sage/geometry/integral_points.pxi +++ b/src/sage/geometry/integral_points.pxi @@ -474,8 +474,8 @@ cpdef rectangular_box_points(list box_min, list box_max, Long ints and non-integral polyhedra are explicitly allowed:: - sage: polytope = Polyhedron([[1], [10*pi.n()]], base_ring=RDF) # optional - sage.symbolic - sage: len(rectangular_box_points([-100], [100], polytope)) # optional - sage.symbolic + sage: polytope = Polyhedron([[1], [10*pi.n()]], base_ring=RDF) # needs sage.symbolic + sage: len(rectangular_box_points([-100], [100], polytope)) # needs sage.symbolic 31 sage: halfplane = Polyhedron(ieqs=[(-1,1,0)]) @@ -488,15 +488,16 @@ cpdef rectangular_box_points(list box_min, list box_max, Using a PPL polyhedron:: - sage: from ppl import Variable, Generator_System, C_Polyhedron, point # optional - pplpy - sage: gs = Generator_System() # optional - pplpy - sage: x = Variable(0); y = Variable(1); z = Variable(2) # optional - pplpy - sage: gs.insert(point(0*x + 1*y + 0*z)) # optional - pplpy - sage: gs.insert(point(0*x + 1*y + 3*z)) # optional - pplpy - sage: gs.insert(point(3*x + 1*y + 0*z)) # optional - pplpy - sage: gs.insert(point(3*x + 1*y + 3*z)) # optional - pplpy - sage: poly = C_Polyhedron(gs) # optional - pplpy - sage: rectangular_box_points([0]*3, [3]*3, poly) # optional - pplpy + sage: # needs pplpy + sage: from ppl import Variable, Generator_System, C_Polyhedron, point + sage: gs = Generator_System() + sage: x = Variable(0); y = Variable(1); z = Variable(2) + sage: gs.insert(point(0*x + 1*y + 0*z)) + sage: gs.insert(point(0*x + 1*y + 3*z)) + sage: gs.insert(point(3*x + 1*y + 0*z)) + sage: gs.insert(point(3*x + 1*y + 3*z)) + sage: poly = C_Polyhedron(gs) + sage: rectangular_box_points([0]*3, [3]*3, poly) ((0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 1, 3), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 1, 3), (3, 1, 0), (3, 1, 1), (3, 1, 2), (3, 1, 3)) @@ -739,7 +740,7 @@ cdef class Inequality_generic: EXAMPLES:: sage: from sage.geometry.integral_points import Inequality_generic - sage: Inequality_generic([2 * pi, sqrt(3), 7/2], -5.5) # optional - sage.symbolic + sage: Inequality_generic([2 * pi, sqrt(3), 7/2], -5.5) # needs sage.symbolic generic: (2*pi, sqrt(3), 7/2) x + -5.50000000000000 >= 0 """ @@ -761,7 +762,7 @@ cdef class Inequality_generic: EXAMPLES:: sage: from sage.geometry.integral_points import Inequality_generic - sage: Inequality_generic([2 * pi, sqrt(3), 7/2], -5.5) # optional - sage.symbolic + sage: Inequality_generic([2 * pi, sqrt(3), 7/2], -5.5) # needs sage.symbolic generic: (2*pi, sqrt(3), 7/2) x + -5.50000000000000 >= 0 """ self.A = A @@ -1131,16 +1132,17 @@ cdef class InequalityCollection: EXAMPLES:: - sage: from ppl import Variable, Generator_System, C_Polyhedron, point # optional - pplpy - sage: gs = Generator_System() # optional - pplpy - sage: x = Variable(0); y = Variable(1); z = Variable(2) # optional - pplpy - sage: gs.insert(point(0*x + 0*y + 1*z)) # optional - pplpy - sage: gs.insert(point(0*x + 3*y + 1*z)) # optional - pplpy - sage: gs.insert(point(3*x + 0*y + 1*z)) # optional - pplpy - sage: gs.insert(point(3*x + 3*y + 1*z)) # optional - pplpy - sage: poly = C_Polyhedron(gs) # optional - pplpy - sage: from sage.geometry.integral_points import InequalityCollection # optional - pplpy - sage: InequalityCollection(poly, [0,2,1], [0]*3, [3]*3 ) # optional - pplpy + sage: # needs pplpy + sage: from ppl import Variable, Generator_System, C_Polyhedron, point + sage: gs = Generator_System() + sage: x = Variable(0); y = Variable(1); z = Variable(2) + sage: gs.insert(point(0*x + 0*y + 1*z)) + sage: gs.insert(point(0*x + 3*y + 1*z)) + sage: gs.insert(point(3*x + 0*y + 1*z)) + sage: gs.insert(point(3*x + 3*y + 1*z)) + sage: poly = C_Polyhedron(gs) + sage: from sage.geometry.integral_points import InequalityCollection + sage: InequalityCollection(poly, [0,2,1], [0]*3, [3]*3 ) The collection of inequalities integer: (0, 1, 0) x + -1 >= 0 integer: (0, -1, 0) x + 1 >= 0 @@ -1191,8 +1193,8 @@ cdef class InequalityCollection: Check that :trac:`21037` is fixed:: sage: P = Polyhedron(vertices=((0, 0), (17,3))) - sage: P += 1/1000*polytopes.regular_polygon(5) # optional - sage.rings.number_field - sage: P.integral_points() # optional - sage.rings.number_field + sage: P += 1/1000*polytopes.regular_polygon(5) # needs sage.rings.number_field + sage: P.integral_points() # needs sage.rings.number_field ((0, 0), (17, 3)) """ cdef list A diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index eab90bd12d2..701b8e43ee8 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -239,7 +239,7 @@ def LatticePolytope(data, compute_vertices=True, n=0, lattice=None): We draw a pretty picture of the polytope in 3-dimensional space:: - sage: p.plot3d().show() # optional - palp sage.plot + sage: p.plot3d().show() # needs palp sage.plot Now we add an extra point, which is in the interior of the polytope... @@ -295,7 +295,7 @@ def LatticePolytope(data, compute_vertices=True, n=0, lattice=None): sage: p.points() Empty collection in 3-d lattice M - sage: p.faces() # optional - sage.graphs + sage: p.faces() # needs sage.graphs ((-1-d lattice polytope in 3-d lattice M,),) """ if isinstance(data, LatticePolytopeClass): @@ -464,7 +464,7 @@ def is_LatticePolytope(x): sage: is_LatticePolytope(1) False sage: p = LatticePolytope([(1,0), (0,1), (-1,-1)]) - sage: p # optional - palp + sage: p # needs palp 2-d reflexive polytope #0 in 2-d lattice M sage: is_LatticePolytope(p) True @@ -763,17 +763,18 @@ def _compute_facets(self): Check that :trac:`28741` is fixed:: + sage: # needs sage.graphs sage: p = LatticePolytope([], lattice=ToricLattice(3).dual()); p -1-d lattice polytope in 3-d lattice M - sage: a = p.faces()[0][0] # optional - sage.graphs + sage: a = p.faces()[0][0] sage: p = LatticePolytope([], lattice=ToricLattice(3).dual()); p -1-d lattice polytope in 3-d lattice M - sage: a = p.faces()[0][0]; a # optional - sage.graphs + sage: a = p.faces()[0][0]; a -1-d lattice polytope in 3-d lattice M - sage: a.facet_normals() # optional - sage.graphs + sage: a.facet_normals() Empty collection in 3-d lattice N - sage: a # optional - sage.graphs + sage: a -1-d lattice polytope in 3-d lattice M """ assert not hasattr(self, "_facet_normals") @@ -966,9 +967,9 @@ def _palp(self, command, reduce_dimension=False): TESTS:: sage: o = lattice_polytope.cross_polytope(3) - sage: o._palp("poly.x -f") # optional - palp + sage: o._palp("poly.x -f") # needs palp 'M:7 6 N:27 8 Pic:17 Cor:0\n' - sage: print(o._palp("nef.x -f -N -p")) # random time information # optional - palp + sage: print(o._palp("nef.x -f -N -p")) # random time information # needs palp M:27 8 N:7 6 codim=2 #part=5 H:[0] P:0 V:2 4 5 0sec 0cpu H:[0] P:2 V:3 4 5 0sec 0cpu @@ -976,18 +977,18 @@ def _palp(self, command, reduce_dimension=False): np=3 d:1 p:1 0sec 0cpu sage: p = LatticePolytope([[1]]) - sage: p._palp("poly.x -f") # optional - palp + sage: p._palp("poly.x -f") # needs palp Traceback (most recent call last): ... ValueError: Cannot run "poly.x -f" for the zero-dimensional polytope! Polytope: 0-d lattice polytope in 1-d lattice M sage: p = LatticePolytope([(1,0,0), (0,1,0), (-1,0,0), (0,-1,0)]) - sage: p._palp("poly.x -f") # optional - palp + sage: p._palp("poly.x -f") # needs palp Traceback (most recent call last): ... ValueError: Cannot run PALP for a 2-dimensional polytope in a 3-dimensional space! - sage: p._palp("poly.x -f", reduce_dimension=True) # optional - palp + sage: p._palp("poly.x -f", reduce_dimension=True) # needs palp 'M:5 4 F:4\n' """ if self.dim() <= 0: @@ -1098,22 +1099,23 @@ def _read_equations(self, data): For a reflexive polytope construct the polar polytope:: + sage: # needs palp sage: p = LatticePolytope([(1,0), (0,1), (-1,-1)]) sage: p.vertices() M( 1, 0), M( 0, 1), M(-1, -1) in 2-d lattice M - sage: s = p.poly_x("e") # optional - palp - sage: print(s) # optional - palp + sage: s = p.poly_x("e") + sage: print(s) 3 2 Vertices of P-dual <-> Equations of P 2 -1 -1 2 -1 -1 - sage: "_polar" in p.__dict__ # optional - palp + sage: "_polar" in p.__dict__ False - sage: p._read_equations(s) # optional - palp - sage: p._polar._vertices # optional - palp + sage: p._read_equations(s) + sage: p._polar._vertices N( 2, -1), N(-1, 2), N(-1, -1) @@ -1121,6 +1123,7 @@ def _read_equations(self, data): For a non-reflexive polytope cache facet equations:: + sage: # needs palp sage: p = LatticePolytope([(1,0), (0,2), (-1,-3 )]) sage: p.vertices() M( 1, 0), @@ -1131,19 +1134,19 @@ def _read_equations(self, data): False sage: "_facet_constants" in p.__dict__ False - sage: s = p.poly_x("e") # optional - palp - sage: print(s) # optional - palp + sage: s = p.poly_x("e") + sage: print(s) 3 2 Equations of P 5 -1 2 -2 -1 2 -3 2 3 - sage: p._read_equations(s) # optional - palp - sage: p._facet_normals # optional - palp + sage: p._read_equations(s) + sage: p._facet_normals N( 5, -1), N(-2, -1), N(-3, 2) in 2-d lattice N - sage: p._facet_constants # optional - palp + sage: p._facet_constants (2, 2, 3) """ if isinstance(data, str): @@ -1210,8 +1213,8 @@ def _read_nef_partitions(self, data): TESTS:: sage: o = lattice_polytope.cross_polytope(3) - sage: s = o.nef_x("-p -N -Lv") # optional - palp - sage: print(s) # random time values # optional - palp + sage: s = o.nef_x("-p -N -Lv") # needs palp + sage: print(s) # random time values # needs palp M:27 8 N:7 6 codim=2 #part=5 3 6 Vertices in N-lattice: 1 0 0 -1 0 0 @@ -1232,8 +1235,8 @@ def _read_nef_partitions(self, data): sage: o_copy = LatticePolytope(o.vertices()) sage: "_nef_partitions" in o_copy.__dict__ False - sage: o_copy._read_nef_partitions(s) # optional - palp - sage: o_copy._nef_partitions # optional - palp + sage: o_copy._read_nef_partitions(s) # needs palp + sage: o_copy._nef_partitions # needs palp [ Nef-partition {0, 1, 3} ⊔ {2, 4, 5}, Nef-partition {0, 1, 2} ⊔ {3, 4, 5}, @@ -1335,7 +1338,7 @@ def _sort_faces(self, faces): sage: o = lattice_polytope.cross_polytope(3) sage: # indirect doctest - sage: for i, face in enumerate(o.faces(0)): # optional - sage.graphs + sage: for i, face in enumerate(o.faces(0)): # needs sage.graphs ....: if face.vertex(0) != o.vertex(i): ....: print("Wrong order!") """ @@ -1380,10 +1383,10 @@ def adjacent(self): EXAMPLES:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.adjacent() # optional - sage.graphs + sage: o.adjacent() # needs sage.graphs () - sage: face = o.faces(1)[0] # optional - sage.graphs - sage: face.adjacent() # optional - sage.graphs + sage: face = o.faces(1)[0] # needs sage.graphs + sage: face.adjacent() # needs sage.graphs (1-d face of 3-d reflexive polytope in 3-d lattice M, 1-d face of 3-d reflexive polytope in 3-d lattice M, 1-d face of 3-d reflexive polytope in 3-d lattice M, @@ -1505,12 +1508,14 @@ def ambient(self): 3-d reflexive polytope in 3-d lattice M sage: o.ambient() is o True - sage: face = o.faces(1)[0] # optional - sage.graphs - sage: face # optional - sage.graphs + + sage: # needs sage.graphs + sage: face = o.faces(1)[0] + sage: face 1-d face of 3-d reflexive polytope in 3-d lattice M - sage: face.ambient() # optional - sage.graphs + sage: face.ambient() 3-d reflexive polytope in 3-d lattice M - sage: face.ambient() is o # optional - sage.graphs + sage: face.ambient() is o True """ return self._ambient @@ -1533,14 +1538,15 @@ def ambient_facet_indices(self): But each of its other faces is contained in one or more facets:: - sage: face = o.faces(1)[0] # optional - sage.graphs - sage: face.ambient_facet_indices() # optional - sage.graphs + sage: # needs sage.graphs + sage: face = o.faces(1)[0] + sage: face.ambient_facet_indices() (4, 5) - sage: face.vertices() # optional - sage.graphs + sage: face.vertices() M(1, 0, 0), M(0, 1, 0) in 3-d lattice M - sage: o.facets()[face.ambient_facet_indices()[0]].vertices() # optional - sage.graphs + sage: o.facets()[face.ambient_facet_indices()[0]].vertices() M(1, 0, 0), M(0, 1, 0), M(0, 0, -1) @@ -1561,10 +1567,10 @@ def ambient_point_indices(self): EXAMPLES:: sage: cube = lattice_polytope.cross_polytope(3).polar() - sage: face = cube.facets()[0] # optional - sage.graphs - sage: face.ambient_point_indices() # optional - palp sage.graphs + sage: face = cube.facets()[0] # needs sage.graphs + sage: face.ambient_point_indices() # needs palp sage.graphs (4, 5, 6, 7, 8, 9, 10, 11, 12) - sage: cube.points(face.ambient_point_indices()) == face.points() # optional - palp sage.graphs + sage: cube.points(face.ambient_point_indices()) == face.points() # needs palp sage.graphs True """ if self._ambient is self: @@ -1587,10 +1593,10 @@ def ambient_ordered_point_indices(self): EXAMPLES:: sage: cube = lattice_polytope.cross_polytope(3).polar() - sage: face = cube.facets()[0] # optional - sage.graphs - sage: face.ambient_ordered_point_indices() # optional - palp sage.graphs + sage: face = cube.facets()[0] # needs sage.graphs + sage: face.ambient_ordered_point_indices() # needs palp sage.graphs (5, 8, 4, 9, 10, 11, 6, 12, 7) - sage: cube.points(face.ambient_ordered_point_indices()) # optional - palp sage.graphs + sage: cube.points(face.ambient_ordered_point_indices()) # needs palp sage.graphs N(-1, -1, -1), N(-1, -1, 0), N(-1, -1, 1), @@ -1621,8 +1627,8 @@ def ambient_vertex_indices(self): sage: o = lattice_polytope.cross_polytope(3) sage: o.ambient_vertex_indices() (0, 1, 2, 3, 4, 5) - sage: face = o.faces(1)[0] # optional - sage.graphs - sage: face.ambient_vertex_indices() # optional - sage.graphs + sage: face = o.faces(1)[0] # needs sage.graphs + sage: face.ambient_vertex_indices() # needs sage.graphs (0, 1) """ return self._ambient_vertex_indices @@ -1641,7 +1647,7 @@ def boundary_point_indices(self): All points but the origin are on the boundary of this square:: sage: square = lattice_polytope.cross_polytope(2).polar() - sage: square.points() # optional - palp + sage: square.points() # needs palp N( 1, 1), N( 1, -1), N(-1, -1), @@ -1652,18 +1658,18 @@ def boundary_point_indices(self): N( 0, 1), N( 1, 0) in 2-d lattice N - sage: square.boundary_point_indices() # optional - palp + sage: square.boundary_point_indices() # needs palp (0, 1, 2, 3, 4, 5, 7, 8) For an edge the boundary is formed by the end points:: - sage: face = square.edges()[0] # optional - sage.graphs - sage: face.points() # optional - sage.graphs + sage: face = square.edges()[0] # needs sage.graphs + sage: face.points() # needs sage.graphs N(-1, -1), N(-1, 1), N(-1, 0) in 2-d lattice N - sage: face.boundary_point_indices() # optional - sage.graphs + sage: face.boundary_point_indices() # needs sage.graphs (0, 1) """ return tuple(i @@ -1683,7 +1689,7 @@ def boundary_points(self): All points but the origin are on the boundary of this square:: sage: square = lattice_polytope.cross_polytope(2).polar() - sage: square.boundary_points() # optional - palp + sage: square.boundary_points() # needs palp N( 1, 1), N( 1, -1), N(-1, -1), @@ -1696,8 +1702,8 @@ def boundary_points(self): For an edge the boundary is formed by the end points:: - sage: face = square.edges()[0] # optional - sage.graphs - sage: face.boundary_points() # optional - sage.graphs + sage: face = square.edges()[0] # needs sage.graphs + sage: face.boundary_points() # needs sage.graphs N(-1, -1), N(-1, 1) in 2-d lattice N @@ -1775,7 +1781,7 @@ def distances(self, point=None): EXAMPLES: The matrix of distances for a 3-dimensional octahedron:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.distances() # optional - palp + sage: o.distances() # needs palp [2 0 0 0 2 2 1] [2 2 0 0 0 2 1] [2 2 2 0 0 0 1] @@ -1794,7 +1800,7 @@ def distances(self, point=None): sage: o.distances([1,2,3/2]) (-3/2, 5/2, 11/2, 3/2, -1/2, -7/2, 1/2, 7/2) - sage: o.distances([1,2,sqrt(2)]) # optional - sage.symbolic + sage: o.distances([1,2,sqrt(2)]) # needs sage.symbolic Traceback (most recent call last): ... TypeError: unable to convert sqrt(2) to an element of Rational Field @@ -1802,17 +1808,17 @@ def distances(self, point=None): Now we create a non-spanning polytope:: sage: p = LatticePolytope([(1,0,0), (0,1,0), (-1,0,0), (0,-1,0)]) - sage: p.distances() # optional - palp + sage: p.distances() # needs palp [2 2 0 0 1] [2 0 0 2 1] [0 0 2 2 1] [0 2 2 0 1] - sage: p.distances((1/2, 3, 0)) # optional - palp + sage: p.distances((1/2, 3, 0)) # needs palp (9/2, -3/2, -5/2, 7/2) This point is not even in the affine subspace of the polytope:: - sage: p.distances((1, 1, 1)) # optional - palp + sage: p.distances((1, 1, 1)) # needs palp (3, 1, -1, 1) """ if point is not None: @@ -1841,16 +1847,17 @@ def dual(self): EXAMPLES:: + sage: # needs sage.graphs sage: o = lattice_polytope.cross_polytope(4) - sage: e = o.edges()[0]; e # optional - sage.graphs + sage: e = o.edges()[0]; e 1-d face of 4-d reflexive polytope in 4-d lattice M - sage: ed = e.dual(); ed # optional - sage.graphs + sage: ed = e.dual(); ed 2-d face of 4-d reflexive polytope in 4-d lattice N - sage: ed.ambient() is e.ambient().polar() # optional - sage.graphs + sage: ed.ambient() is e.ambient().polar() True - sage: e.ambient_vertex_indices() == ed.ambient_facet_indices() # optional - sage.graphs + sage: e.ambient_vertex_indices() == ed.ambient_facet_indices() True - sage: e.ambient_facet_indices() == ed.ambient_vertex_indices() # optional - sage.graphs + sage: e.ambient_facet_indices() == ed.ambient_vertex_indices() True """ for f in self._ambient.polar().faces(codim=self.dim() + 1): @@ -1893,11 +1900,11 @@ def edges(self): EXAMPLES:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.edges() # optional - sage.graphs + sage: o.edges() # needs sage.graphs (1-d face of 3-d reflexive polytope in 3-d lattice M, ... 1-d face of 3-d reflexive polytope in 3-d lattice M) - sage: len(o.edges()) # optional - sage.graphs + sage: len(o.edges()) # needs sage.graphs 12 """ return self.faces(dim=1) @@ -1920,12 +1927,12 @@ def face_lattice(self): Let's take a look at the face lattice of a square:: sage: square = LatticePolytope([(0,0), (1,0), (1,1), (0,1)]) - sage: L = square.face_lattice(); L # optional - sage.graphs + sage: L = square.face_lattice(); L # needs sage.graphs Finite lattice containing 10 elements with distinguished linear extension To see all faces arranged by dimension, you can do this:: - sage: for level in L.level_sets(): print(level) # optional - sage.graphs + sage: for level in L.level_sets(): print(level) # needs sage.graphs [-1-d face of 2-d lattice polytope in 2-d lattice M] [0-d face of 2-d lattice polytope in 2-d lattice M, 0-d face of 2-d lattice polytope in 2-d lattice M, @@ -1939,31 +1946,31 @@ def face_lattice(self): For a particular face you can look at its actual vertices... :: - sage: face = L.level_sets()[1][0] # optional - sage.graphs - sage: face.vertices() # optional - sage.graphs + sage: face = L.level_sets()[1][0] # needs sage.graphs + sage: face.vertices() # needs sage.graphs M(0, 0) in 2-d lattice M ... or you can see the index of the vertex of the original polytope that corresponds to the above one:: - sage: face.ambient_vertex_indices() # optional - sage.graphs + sage: face.ambient_vertex_indices() # needs sage.graphs (0,) - sage: square.vertex(0) # optional - sage.graphs + sage: square.vertex(0) M(0, 0) An alternative to extracting faces from the face lattice is to use :meth:`faces` method:: - sage: face is square.faces(dim=0)[0] # optional - sage.graphs + sage: face is square.faces(dim=0)[0] # needs sage.graphs True The advantage of working with the face lattice directly is that you can (relatively easily) get faces that are related to the given one:: - sage: face = L.level_sets()[1][0] # optional - sage.graphs - sage: D = L.hasse_diagram() # optional - sage.graphs - sage: sorted(D.neighbors(face)) # optional - sage.graphs + sage: face = L.level_sets()[1][0] # needs sage.graphs + sage: D = L.hasse_diagram() # needs sage.graphs + sage: sorted(D.neighbors(face)) # needs sage.graphs [-1-d face of 2-d lattice polytope in 2-d lattice M, 1-d face of 2-d lattice polytope in 2-d lattice M, 1-d face of 2-d lattice polytope in 2-d lattice M] @@ -1971,43 +1978,45 @@ def face_lattice(self): However, you can achieve some of this functionality using :meth:`facets`, :meth:`facet_of`, and :meth:`adjacent` methods:: - sage: face = square.faces(0)[0] # optional - sage.graphs - sage: face # optional - sage.graphs + sage: # needs sage.graphs + sage: face = square.faces(0)[0] + sage: face 0-d face of 2-d lattice polytope in 2-d lattice M - sage: face.vertices() # optional - sage.graphs + sage: face.vertices() M(0, 0) in 2-d lattice M - sage: face.facets() # optional - sage.graphs + sage: face.facets() (-1-d face of 2-d lattice polytope in 2-d lattice M,) - sage: face.facet_of() # optional - sage.graphs + sage: face.facet_of() (1-d face of 2-d lattice polytope in 2-d lattice M, 1-d face of 2-d lattice polytope in 2-d lattice M) - sage: face.adjacent() # optional - sage.graphs + sage: face.adjacent() (0-d face of 2-d lattice polytope in 2-d lattice M, 0-d face of 2-d lattice polytope in 2-d lattice M) - sage: face.adjacent()[0].vertices() # optional - sage.graphs + sage: face.adjacent()[0].vertices() M(1, 0) in 2-d lattice M Note that if ``p`` is a face of ``superp``, then the face lattice of ``p`` consists of (appropriate) faces of ``superp``:: + sage: # needs sage.graphs sage: superp = LatticePolytope([(1,2,3,4), (5,6,7,8), ....: (1,2,4,8), (1,3,9,7)]) - sage: superp.face_lattice() # optional - sage.graphs + sage: superp.face_lattice() Finite lattice containing 16 elements with distinguished linear extension - sage: superp.face_lattice().top() # optional - sage.graphs + sage: superp.face_lattice().top() 3-d lattice polytope in 4-d lattice M - sage: p = superp.facets()[0] # optional - sage.graphs - sage: p # optional - sage.graphs + sage: p = superp.facets()[0] + sage: p 2-d face of 3-d lattice polytope in 4-d lattice M - sage: p.face_lattice() # optional - sage.graphs + sage: p.face_lattice() Finite poset containing 8 elements with distinguished linear extension - sage: p.face_lattice().bottom() # optional - sage.graphs + sage: p.face_lattice().bottom() -1-d face of 3-d lattice polytope in 4-d lattice M - sage: p.face_lattice().top() # optional - sage.graphs + sage: p.face_lattice().top() 2-d face of 3-d lattice polytope in 4-d lattice M - sage: p.face_lattice().top() is p # optional - sage.graphs + sage: p.face_lattice().top() is p True """ if self._ambient is self: @@ -2097,7 +2106,7 @@ def faces(self, dim=None, codim=None): Let's take a look at the faces of a square:: sage: square = LatticePolytope([(0,0), (1,0), (1,1), (0,1)]) - sage: square.faces() # optional - sage.graphs + sage: square.faces() # needs sage.graphs ((-1-d face of 2-d lattice polytope in 2-d lattice M,), (0-d face of 2-d lattice polytope in 2-d lattice M, 0-d face of 2-d lattice polytope in 2-d lattice M, @@ -2111,7 +2120,7 @@ def faces(self, dim=None, codim=None): Its faces of dimension one (i.e., edges):: - sage: square.faces(dim=1) # optional - sage.graphs + sage: square.faces(dim=1) # needs sage.graphs (1-d face of 2-d lattice polytope in 2-d lattice M, 1-d face of 2-d lattice polytope in 2-d lattice M, 1-d face of 2-d lattice polytope in 2-d lattice M, @@ -2119,16 +2128,16 @@ def faces(self, dim=None, codim=None): Its faces of codimension one are the same (also edges):: - sage: square.faces(codim=1) is square.faces(dim=1) # optional - sage.graphs + sage: square.faces(codim=1) is square.faces(dim=1) # needs sage.graphs True Let's pick a particular face:: - sage: face = square.faces(dim=1)[0] # optional - sage.graphs + sage: face = square.faces(dim=1)[0] # needs sage.graphs Now you can look at the actual vertices of this face... :: - sage: face.vertices() # optional - sage.graphs + sage: face.vertices() # needs sage.graphs M(0, 0), M(0, 1) in 2-d lattice M @@ -2136,9 +2145,9 @@ def faces(self, dim=None, codim=None): ... or you can see indices of the vertices of the original polytope that correspond to the above ones:: - sage: face.ambient_vertex_indices() # optional - sage.graphs + sage: face.ambient_vertex_indices() # needs sage.graphs (0, 3) - sage: square.vertices(face.ambient_vertex_indices()) # optional - sage.graphs + sage: square.vertices(face.ambient_vertex_indices()) # needs sage.graphs M(0, 0), M(0, 1) in 2-d lattice M @@ -2363,13 +2372,14 @@ def facet_of(self): EXAMPLES:: + sage: # needs sage.graphs sage: square = LatticePolytope([(0,0), (1,0), (1,1), (0,1)]) - sage: square.facet_of() # optional - sage.graphs + sage: square.facet_of() () - sage: face = square.faces(0)[0] # optional - sage.graphs - sage: len(face.facet_of()) # optional - sage.graphs + sage: face = square.faces(0)[0] + sage: len(face.facet_of()) 2 - sage: face.facet_of()[1] # optional - sage.graphs + sage: face.facet_of()[1] 1-d face of 2-d lattice polytope in 2-d lattice M """ L = self._ambient.face_lattice() @@ -2387,11 +2397,11 @@ def facets(self): EXAMPLES:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.facets() # optional - sage.graphs + sage: o.facets() # needs sage.graphs (2-d face of 3-d reflexive polytope in 3-d lattice M, ... 2-d face of 3-d reflexive polytope in 3-d lattice M) - sage: len(o.facets()) # optional - sage.graphs + sage: len(o.facets()) # needs sage.graphs 8 """ return self.faces(codim=1) @@ -2419,14 +2429,14 @@ def incidence_matrix(self): [0 1 1 0] [1 1 0 0] [1 0 0 1] - sage: o.faces(1)[0].incidence_matrix() # optional - sage.graphs + sage: o.faces(1)[0].incidence_matrix() # needs sage.graphs [1 0] [0 1] sage: o = lattice_polytope.cross_polytope(4) sage: o.incidence_matrix().column(3).nonzero_positions() [3, 4, 5, 6] - sage: o.facets()[3].ambient_vertex_indices() # optional - sage.graphs + sage: o.facets()[3].ambient_vertex_indices() # needs sage.graphs (3, 4, 5, 6) TESTS:: @@ -2470,7 +2480,7 @@ def index(self): database:: sage: d = lattice_polytope.cross_polytope(2) - sage: d.index() # optional - palp + sage: d.index() # needs palp 3 Note that polytopes with the same index are not necessarily the @@ -2492,7 +2502,7 @@ def index(self): But they are in the same `GL(Z^n)` orbit and have the same normal form:: - sage: d.normal_form() # optional - palp + sage: d.normal_form() # needs palp M( 1, 0), M( 0, 1), M( 0, -1), @@ -2531,7 +2541,7 @@ def interior_point_indices(self): The origin is the only interior point of this square:: sage: square = lattice_polytope.cross_polytope(2).polar() - sage: square.points() # optional - palp + sage: square.points() # needs palp N( 1, 1), N( 1, -1), N(-1, -1), @@ -2542,18 +2552,18 @@ def interior_point_indices(self): N( 0, 1), N( 1, 0) in 2-d lattice N - sage: square.interior_point_indices() # optional - palp + sage: square.interior_point_indices() # needs palp (6,) Its edges also have a single interior point each:: - sage: face = square.edges()[0] # optional - sage.graphs - sage: face.points() # optional - sage.graphs + sage: face = square.edges()[0] # needs sage.graphs + sage: face.points() # needs sage.graphs N(-1, -1), N(-1, 1), N(-1, 0) in 2-d lattice N - sage: face.interior_point_indices() # optional - sage.graphs + sage: face.interior_point_indices() # needs sage.graphs (2,) """ return tuple(i @@ -2573,14 +2583,14 @@ def interior_points(self): The origin is the only interior point of this square:: sage: square = lattice_polytope.cross_polytope(2).polar() - sage: square.interior_points() # optional - palp + sage: square.interior_points() # needs palp N(0, 0) in 2-d lattice N Its edges also have a single interior point each:: - sage: face = square.edges()[0] # optional - sage.graphs - sage: face.interior_points() # optional - sage.graphs + sage: face = square.edges()[0] # needs sage.graphs + sage: face.interior_points() # needs sage.graphs N(-1, 0) in 2-d lattice N """ @@ -2666,7 +2676,7 @@ def ambient_vector_space(self, base_field=None): sage: p = LatticePolytope([(1,0)]) sage: p.ambient_vector_space() Vector space of dimension 2 over Rational Field - sage: p.ambient_vector_space(AA) # optional - sage.rings.number_field + sage: p.ambient_vector_space(AA) # needs sage.rings.number_field Vector space of dimension 2 over Algebraic Real Field """ return self.lattice().vector_space(base_field=base_field) @@ -2727,7 +2737,7 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, Nef-partitions of the 4-dimensional cross-polytope:: sage: p = lattice_polytope.cross_polytope(4) - sage: p.nef_partitions() # optional - palp + sage: p.nef_partitions() # needs palp [ Nef-partition {0, 1, 4, 5} ⊔ {2, 3, 6, 7} (direct product), Nef-partition {0, 1, 2, 4} ⊔ {3, 5, 6, 7}, @@ -2741,7 +2751,7 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, Now we omit projections:: - sage: p.nef_partitions(keep_projections=False) # optional - palp + sage: p.nef_partitions(keep_projections=False) # needs palp [ Nef-partition {0, 1, 4, 5} ⊔ {2, 3, 6, 7} (direct product), Nef-partition {0, 1, 2, 4} ⊔ {3, 5, 6, 7}, @@ -2754,7 +2764,7 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, Currently Hodge numbers cannot be computed for a given nef-partition:: - sage: p.nef_partitions()[1].hodge_numbers() # optional - palp + sage: p.nef_partitions()[1].hodge_numbers() # needs palp Traceback (most recent call last): ... NotImplementedError: use nef_partitions(hodge_numbers=True)! @@ -2762,7 +2772,7 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, But they can be obtained from ``nef.x`` for all nef-partitions at once. Partitions will be exactly the same:: - sage: p.nef_partitions(hodge_numbers=True) # long time (2s on sage.math, 2011) # optional - palp + sage: p.nef_partitions(hodge_numbers=True) # long time (2s on sage.math, 2011), needs palp [ Nef-partition {0, 1, 4, 5} ⊔ {2, 3, 6, 7} (direct product), Nef-partition {0, 1, 2, 4} ⊔ {3, 5, 6, 7}, @@ -2776,26 +2786,26 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, Now it is possible to get Hodge numbers:: - sage: p.nef_partitions(hodge_numbers=True)[1].hodge_numbers() # optional - palp + sage: p.nef_partitions(hodge_numbers=True)[1].hodge_numbers() # needs palp (20,) Since nef-partitions are cached, their Hodge numbers are accessible after the first request, even if you do not specify ``hodge_numbers=True`` anymore:: - sage: p.nef_partitions()[1].hodge_numbers() # optional - palp + sage: p.nef_partitions()[1].hodge_numbers() # needs palp (20,) We illustrate removal of symmetric partitions on a diamond:: sage: p = lattice_polytope.cross_polytope(2) - sage: p.nef_partitions() # optional - palp + sage: p.nef_partitions() # needs palp [ Nef-partition {0, 2} ⊔ {1, 3} (direct product), Nef-partition {0, 1} ⊔ {2, 3}, Nef-partition {0, 1, 2} ⊔ {3} (projection) ] - sage: p.nef_partitions(keep_symmetric=True) # optional - palp + sage: p.nef_partitions(keep_symmetric=True) # needs palp [ Nef-partition {0, 1, 3} ⊔ {2} (projection), Nef-partition {0, 2, 3} ⊔ {1} (projection), @@ -2810,7 +2820,7 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, sage: p = LatticePolytope([(1,0,0), (0,1,0), (0,0,2), ....: (-1,0,0), (0,-1,0), (0,0,-1)]) - sage: p.nef_partitions() # optional - palp + sage: p.nef_partitions() # needs palp Traceback (most recent call last): ... ValueError: The given polytope is not reflexive! @@ -2864,8 +2874,8 @@ def nef_x(self, keys): nef-partitions:: sage: o = lattice_polytope.cross_polytope(3) - sage: s = o.nef_x("-N -V -p") # optional - palp - sage: s # output contains random time # optional - palp + sage: s = o.nef_x("-N -V -p") # needs palp + sage: s # output contains random time # needs palp M:27 8 N:7 6 codim=2 #part=5 3 6 Vertices of P: 1 0 0 -1 0 0 @@ -2952,7 +2962,7 @@ def normal_form(self, algorithm="palp", permutation=False): M(-1, 0), M( 0, -1) in 2-d lattice M - sage: d.normal_form() # optional - palp + sage: d.normal_form() # needs palp M( 1, 0), M( 0, 1), M( 0, -1), @@ -2961,9 +2971,9 @@ def normal_form(self, algorithm="palp", permutation=False): The diamond is the 3rd polytope in the internal database:: - sage: d.index() # optional - palp + sage: d.index() # needs palp 3 - sage: d # optional - palp + sage: d # needs palp 2-d reflexive polytope #3 in 2-d lattice M You can get it in its normal form (in the default lattice) as :: @@ -2988,7 +2998,7 @@ def normal_form(self, algorithm="palp", permutation=False): We can perform the same examples using other algorithms:: sage: o = lattice_polytope.cross_polytope(2) - sage: o.normal_form(algorithm="palp_native") + sage: o.normal_form(algorithm="palp_native") # needs sage.groups M( 1, 0), M( 0, 1), M( 0, -1), @@ -2996,7 +3006,7 @@ def normal_form(self, algorithm="palp", permutation=False): in 2-d lattice M sage: o = lattice_polytope.cross_polytope(2) - sage: o.normal_form(algorithm="palp_modified") + sage: o.normal_form(algorithm="palp_modified") # needs sage.groups M( 1, 0), M( 0, 1), M( 0, -1), @@ -3054,13 +3064,13 @@ def _palp_modified_normal_form(self, permutation=False): M(-1, 0), M( 0, -1) in 2-d lattice M - sage: o._palp_modified_normal_form() # optional - sage.graphs + sage: o._palp_modified_normal_form() # needs sage.graphs sage.groups M( 1, 0), M( 0, 1), M( 0, -1), M(-1, 0) in 2-d lattice M - sage: o._palp_modified_normal_form(permutation=True) # optional - sage.graphs + sage: o._palp_modified_normal_form(permutation=True) # needs sage.graphs sage.groups (M( 1, 0), M( 0, 1), M( 0, -1), @@ -3107,13 +3117,13 @@ def _palp_native_normal_form(self, permutation=False): M(-1, 0), M( 0, -1) in 2-d lattice M - sage: o._palp_native_normal_form() # optional - sage.groups + sage: o._palp_native_normal_form() # needs sage.groups M( 1, 0), M( 0, 1), M( 0, -1), M(-1, 0) in 2-d lattice M - sage: o._palp_native_normal_form(permutation=True) # optional - sage.groups + sage: o._palp_native_normal_form(permutation=True) # needs sage.groups (M( 1, 0), M( 0, 1), M( 0, -1), @@ -3158,23 +3168,23 @@ def _palp_PM_max(self, check=False): sage: o = lattice_polytope.cross_polytope(2) sage: PM = o.vertex_facet_pairing_matrix() - sage: PM_max = PM.permutation_normal_form() # optional - sage.graphs - sage: PM_max == o._palp_PM_max() # optional - sage.graphs + sage: PM_max = PM.permutation_normal_form() # needs sage.graphs + sage: PM_max == o._palp_PM_max() # needs sage.graphs sage.groups True sage: P2 = ReflexivePolytope(2, 0) - sage: PM_max, permutations = P2._palp_PM_max(check=True) - sage: PM_max + sage: PM_max, permutations = P2._palp_PM_max(check=True) # needs sage.groups + sage: PM_max # needs sage.graphs [3 0 0] [0 3 0] [0 0 3] - sage: list(permutations.values()) + sage: list(permutations.values()) # needs sage.groups [[(1,2,3), (1,2,3)], [(1,3,2), (1,3,2)], [(1,3), (1,3)], [(1,2), (1,2)], [(), ()], [(2,3), (2,3)]] - sage: PM_max.automorphisms_of_rows_and_columns() + sage: PM_max.automorphisms_of_rows_and_columns() # needs sage.graphs [((), ()), ((1,2,3), (1,2,3)), ((1,3,2), (1,3,2)), @@ -3396,10 +3406,10 @@ def npoints(self): octahedron and its polar cube:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.npoints() # optional - palp + sage: o.npoints() # needs palp 7 sage: cube = o.polar() - sage: cube.npoints() # optional - palp + sage: cube.npoints() # needs palp 27 """ try: @@ -3435,9 +3445,9 @@ def origin(self): EXAMPLES:: sage: p = lattice_polytope.cross_polytope(2) - sage: p.origin() # optional - palp + sage: p.origin() # needs palp 4 - sage: p.point(p.origin()) # optional - palp + sage: p.point(p.origin()) # needs palp M(0, 0) sage: p = LatticePolytope(([1],[2])) @@ -3550,30 +3560,30 @@ def plot3d(self, EXAMPLES: The default plot of a cube:: sage: c = lattice_polytope.cross_polytope(3).polar() - sage: c.plot3d() # optional - palp sage.plot + sage: c.plot3d() # needs palp sage.plot Graphics3d Object Plot without facets and points, shown without the frame:: - sage: c.plot3d(show_facets=false, # optional - palp sage.plot + sage: c.plot3d(show_facets=false, # needs palp sage.plot ....: show_points=false).show(frame=False) Plot with facets of different colors:: - sage: c.plot3d(facet_colors=rainbow(c.nfacets(), 'rgbtuple')) # optional - palp sage.plot + sage: c.plot3d(facet_colors=rainbow(c.nfacets(), 'rgbtuple')) # needs palp sage.plot Graphics3d Object It is also possible to plot lower dimensional polytops in 3D (let's also change labels of vertices):: sage: c2 = lattice_polytope.cross_polytope(2) - sage: c2.plot3d(vlabels=["A", "B", "C", "D"]) # optional - palp sage.plot + sage: c2.plot3d(vlabels=["A", "B", "C", "D"]) # needs palp sage.plot Graphics3d Object TESTS:: sage: p = LatticePolytope([[0,0,0],[0,1,1],[1,0,1],[1,1,0]]) - sage: p.plot3d() # optional - palp sage.plot + sage: p.plot3d() # needs palp sage.plot Graphics3d Object """ dim = self.dim() @@ -3664,7 +3674,7 @@ def show3d(self): EXAMPLES:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.show3d() # optional - palp sage.plot + sage: o.show3d() # needs palp sage.plot """ self.plot3d().show(axis=False, frame=False) @@ -3684,14 +3694,14 @@ def point(self, i): M( 0, -1, 0), M( 0, 0, -1) in 3-d lattice M - sage: o.point(1) # optional - palp + sage: o.point(1) # needs palp M(0, 1, 0) The only other point in the octahedron is the origin:: - sage: o.point(6) # optional - palp + sage: o.point(6) # needs palp M(0, 0, 0) - sage: o.points() # optional - palp + sage: o.points() # needs palp M( 1, 0, 0), M( 0, 1, 0), M( 0, 0, 1), @@ -3720,7 +3730,7 @@ def points(self, *args, **kwds): Lattice points of the octahedron and its polar cube:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.points() # optional - palp + sage: o.points() # needs palp M( 1, 0, 0), M( 0, 1, 0), M( 0, 0, 1), @@ -3730,7 +3740,7 @@ def points(self, *args, **kwds): M( 0, 0, 0) in 3-d lattice M sage: cube = o.polar() - sage: cube.points() # optional - palp + sage: cube.points() # needs palp N( 1, -1, -1), N( 1, 1, -1), N( 1, 1, 1), @@ -3763,7 +3773,7 @@ def points(self, *args, **kwds): Lattice points of a 2-dimensional diamond in a 3-dimensional space:: sage: p = LatticePolytope([(1,0,0), (0,1,0), (-1,0,0), (0,-1,0)]) - sage: p.points() # optional - palp + sage: p.points() # needs palp M( 1, 0, 0), M( 0, 1, 0), M(-1, 0, 0), @@ -3773,7 +3783,7 @@ def points(self, *args, **kwds): Only two of the above points:: - sage: p.points(1, 3) # optional - palp + sage: p.points(1, 3) # needs palp M(0, 1, 0), M(0, -1, 0) in 3-d lattice M @@ -3904,7 +3914,7 @@ def poly_x(self, keys, reduce_dimension=False): reflexive or not:: sage: o = lattice_polytope.cross_polytope(3) - sage: print(o.poly_x("e")) # optional - palp + sage: print(o.poly_x("e")) # needs palp 8 3 Vertices of P-dual <-> Equations of P -1 -1 1 1 -1 1 @@ -3922,7 +3932,7 @@ def poly_x(self, keys, reduce_dimension=False): sage: BIG = lattice_polytope.cross_polytope(7) sage: BIG 7-d reflexive polytope in 7-d lattice M - sage: BIG.poly_x("e") # optional - palp + sage: BIG.poly_x("e") # needs palp Traceback (most recent call last): ... ValueError: Error executing 'poly.x -fe' for the given polytope! @@ -3933,7 +3943,7 @@ def poly_x(self, keys, reduce_dimension=False): could, it would crush anyway):: sage: p = LatticePolytope([(1,0,0), (0,1,0), (-1,0,0), (0,-1,0)]) - sage: p.poly_x("e") # optional - palp + sage: p.poly_x("e") # needs palp Traceback (most recent call last): ... ValueError: Cannot run PALP for a 2-dimensional polytope in a 3-dimensional space! @@ -3941,7 +3951,7 @@ def poly_x(self, keys, reduce_dimension=False): But if you know what you are doing, you can call it for the polytope in some basis of the spanned space:: - sage: print(p.poly_x("e", reduce_dimension=True)) # optional - palp + sage: print(p.poly_x("e", reduce_dimension=True)) # needs palp 4 2 Equations of P -1 1 0 1 1 2 @@ -3958,9 +3968,9 @@ def skeleton(self): EXAMPLES:: sage: d = lattice_polytope.cross_polytope(2) - sage: g = d.skeleton(); g # optional - palp sage.graphs + sage: g = d.skeleton(); g # needs palp sage.graphs Graph on 4 vertices - sage: g.edges(sort=True) # optional - palp sage.graphs + sage: g.edges(sort=True) # needs palp sage.graphs [(0, 1, None), (0, 3, None), (1, 2, None), (2, 3, None)] """ skeleton = Graph() @@ -3980,35 +3990,35 @@ def skeleton_points(self, k=1): sage: o = lattice_polytope.cross_polytope(3) sage: c = o.polar() - sage: c.skeleton_points() # optional - palp sage.graphs + sage: c.skeleton_points() # needs palp sage.graphs [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 19, 21, 22, 23, 25, 26] The default was 1-skeleton:: - sage: c.skeleton_points(k=1) # optional - palp sage.graphs + sage: c.skeleton_points(k=1) # needs palp sage.graphs [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 19, 21, 22, 23, 25, 26] 0-skeleton just lists all vertices:: - sage: c.skeleton_points(k=0) # optional - palp sage.graphs + sage: c.skeleton_points(k=0) # needs palp sage.graphs [0, 1, 2, 3, 4, 5, 6, 7] 2-skeleton lists all points except for the origin (point #17):: - sage: c.skeleton_points(k=2) # optional - palp sage.graphs + sage: c.skeleton_points(k=2) # needs palp sage.graphs [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26] 3-skeleton includes all points:: - sage: c.skeleton_points(k=3) # optional - palp sage.graphs + sage: c.skeleton_points(k=3) # needs palp [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] It is OK to compute higher dimensional skeletons - you will get the list of all points:: - sage: c.skeleton_points(k=100) # optional - palp sage.graphs + sage: c.skeleton_points(k=100) # needs palp [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26] """ @@ -4036,7 +4046,7 @@ def skeleton_show(self, normal=None): EXAMPLES: Show a pretty picture of the octahedron:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.skeleton_show([1,2,4]) # optional - palp sage.plot + sage: o.skeleton_show([1,2,4]) # needs palp sage.plot Does not work for a diamond at the moment:: @@ -4064,7 +4074,7 @@ def traverse_boundary(self): EXAMPLES:: sage: p = lattice_polytope.cross_polytope(2).polar() - sage: p.traverse_boundary() # optional - sage.graphs + sage: p.traverse_boundary() # needs sage.graphs [3, 0, 1, 2] """ if self.dim() != 2: @@ -4193,9 +4203,9 @@ def is_NefPartition(x): sage: is_NefPartition(1) False sage: o = lattice_polytope.cross_polytope(3) - sage: np = o.nef_partitions()[0]; np # optional - palp + sage: np = o.nef_partitions()[0]; np # needs palp Nef-partition {0, 1, 3} ⊔ {2, 4, 5} - sage: is_NefPartition(np) # optional - palp + sage: is_NefPartition(np) # needs palp True """ return isinstance(x, NefPartition) @@ -4333,7 +4343,7 @@ class NefPartition(SageObject, Hashable): nef-partitions of a given reflexive polytope (they will be computed using ``nef.x`` program from PALP):: - sage: o.nef_partitions() # optional - palp + sage: o.nef_partitions() # needs palp [ Nef-partition {0, 1, 3} ⊔ {2, 4, 5}, Nef-partition {0, 1, 3, 4} ⊔ {2, 5} (direct product), @@ -4350,8 +4360,8 @@ def __init__(self, data, Delta_polar, check=True): TESTS:: sage: o = lattice_polytope.cross_polytope(3) - sage: np = o.nef_partitions()[0] # optional - palp - sage: TestSuite(np).run() # optional - palp + sage: np = o.nef_partitions()[0] # needs palp + sage: TestSuite(np).run() # needs palp """ if check and not Delta_polar.is_reflexive(): raise ValueError("nef-partitions can be constructed for reflexive " @@ -4386,9 +4396,9 @@ def __eq__(self, other): sage: np = NefPartition([0, 0, 1, 0, 1, 1], o) sage: np == np True - sage: np == o.nef_partitions()[0] # optional - palp + sage: np == o.nef_partitions()[0] # needs palp True - sage: np == o.nef_partitions()[1] # optional - palp + sage: np == o.nef_partitions()[1] # needs palp False sage: np2 = NefPartition(np._vertex_to_part, o) sage: np2 is np @@ -4447,9 +4457,9 @@ def __ne__(self, other): sage: np = NefPartition([0, 0, 1, 0, 1, 1], o) sage: np != np False - sage: np != o.nef_partitions()[0] # optional - palp + sage: np != o.nef_partitions()[0] # needs palp False - sage: np != o.nef_partitions()[1] # optional - palp + sage: np != o.nef_partitions()[1] # needs palp True sage: np2 = NefPartition(np._vertex_to_part, o) sage: np2 is np @@ -4729,14 +4739,15 @@ def hodge_numbers(self): Currently, you need to request Hodge numbers when you compute nef-partitions:: + sage: # long time, needs palp sage: p = lattice_polytope.cross_polytope(5) - sage: np = p.nef_partitions()[0] # long time (4s on sage.math, 2011) # optional - palp - sage: np.hodge_numbers() # long time # optional - palp + sage: np = p.nef_partitions()[0] # 4s on sage.math, 2011 + sage: np.hodge_numbers() Traceback (most recent call last): ... NotImplementedError: use nef_partitions(hodge_numbers=True)! - sage: np = p.nef_partitions(hodge_numbers=True)[0] # long time (13s on sage.math, 2011) # optional - palp - sage: np.hodge_numbers() # long time # optional - palp + sage: np = p.nef_partitions(hodge_numbers=True)[0] # 13s on sage.math, 2011 + sage: np.hodge_numbers() (19, 19) """ try: @@ -4914,11 +4925,11 @@ def part(self, i, all_points=False): Nef-partition {0, 1, 3} ⊔ {2, 4, 5} sage: np.part(0) (0, 1, 3) - sage: np.part(0, all_points=True) # optional - palp + sage: np.part(0, all_points=True) # needs palp (0, 1, 3) sage: np.dual().part(0) (0, 1, 2, 3) - sage: np.dual().part(0, all_points=True) # optional - palp + sage: np.dual().part(0, all_points=True) # needs palp (0, 1, 2, 3, 8) """ return self.parts(all_points)[i] @@ -4948,11 +4959,11 @@ def parts(self, all_points=False): Nef-partition {0, 1, 3} ⊔ {2, 4, 5} sage: np.parts() ((0, 1, 3), (2, 4, 5)) - sage: np.parts(all_points=True) # optional - palp + sage: np.parts(all_points=True) # needs palp ((0, 1, 3), (2, 4, 5)) sage: np.dual().parts() ((0, 1, 2, 3), (4, 5, 6, 7)) - sage: np.dual().parts(all_points=True) # optional - palp + sage: np.dual().parts(all_points=True) # needs palp ((0, 1, 2, 3, 8), (4, 5, 6, 7, 10)) """ parts = [[] for _ in range(self._nparts)] @@ -5026,29 +5037,29 @@ def part_of_point(self, i): sage: p = LatticePolytope([(1,0,0), (0,1,0), (0,0,1), (0,1,-1), ....: (0,-1,1), (-1,1,0), (0,-1,-1), (-1,-1,0), (-1,-1,2)]) - sage: np = p.nef_partitions()[0]; np # optional - palp + sage: np = p.nef_partitions()[0]; np # needs palp Nef-partition {1, 2, 5, 7, 8} ⊔ {0, 3, 4, 6} sage: p.nvertices() 9 - sage: p.npoints() # optional - palp + sage: p.npoints() # needs palp 15 We see that the polytope has 6 more points in addition to vertices. One of them is the origin:: - sage: p.origin() # optional - palp + sage: p.origin() # needs palp 14 - sage: np.part_of_point(14) # optional - palp + sage: np.part_of_point(14) # needs palp Traceback (most recent call last): ... ValueError: the origin belongs to all parts! But the remaining 5 are partitioned by ``np``:: - sage: [n for n in range(p.npoints()) # optional - palp + sage: [n for n in range(p.npoints()) # needs palp ....: if p.origin() != n and np.part_of_point(n) == 0] [1, 2, 5, 7, 8, 9, 11, 13] - sage: [n for n in range(p.npoints()) # optional - palp + sage: [n for n in range(p.npoints()) # needs palp ....: if p.origin() != n and np.part_of_point(n) == 1] [0, 3, 4, 6, 10, 12] """ @@ -5081,27 +5092,29 @@ def _palp(command, polytopes, reduce_dimension=False): TESTS:: + sage: # needs palp sage: o = lattice_polytope.cross_polytope(3) - sage: result_name = lattice_polytope._palp("poly.x -f", [o]) # optional - palp - sage: f = open(result_name) # optional - palp - sage: f.readlines() # optional - palp + sage: result_name = lattice_polytope._palp("poly.x -f", [o]) + sage: f = open(result_name) + sage: f.readlines() ['M:7 6 N:27 8 Pic:17 Cor:0\n'] - sage: f.close() # optional - palp - sage: os.remove(result_name) # optional - palp + sage: f.close() + sage: os.remove(result_name) sage: p = LatticePolytope([(1,0,0), (0,1,0), (-1,0,0), (0,-1,0)]) - sage: lattice_polytope._palp("poly.x -f", [p]) # optional - palp + sage: lattice_polytope._palp("poly.x -f", [p]) # needs palp Traceback (most recent call last): ... ValueError: Cannot run PALP for a 2-dimensional polytope in a 3-dimensional space! - sage: result_name = lattice_polytope._palp("poly.x -f", [p], # optional - palp + sage: # needs palp + sage: result_name = lattice_polytope._palp("poly.x -f", [p], ....: reduce_dimension=True) - sage: f = open(result_name) # optional - palp - sage: f.readlines() # optional - palp + sage: f = open(result_name) + sage: f.readlines() ['M:5 4 F:4\n'] - sage: f.close() # optional - palp - sage: os.remove(result_name) # optional - palp + sage: f.close() + sage: os.remove(result_name) """ if _palp_dimension is not None: dot = command.find(".") @@ -5172,9 +5185,9 @@ def _palp_canonical_order(V, PM_max, permutations): sage: L = lattice_polytope.cross_polytope(2) sage: V = L.vertices() - sage: PM_max, permutations = L._palp_PM_max(check=True) # optional - sage.groups + sage: PM_max, permutations = L._palp_PM_max(check=True) # needs sage.groups sage: from sage.geometry.lattice_polytope import _palp_canonical_order - sage: _palp_canonical_order(V, PM_max, permutations) # optional - sage.groups + sage: _palp_canonical_order(V, PM_max, permutations) # needs sage.groups (M( 1, 0), M( 0, 1), M( 0, -1), @@ -5228,9 +5241,9 @@ def _palp_convert_permutation(permutation): EXAMPLES:: sage: from sage.geometry.lattice_polytope import _palp_convert_permutation - sage: _palp_convert_permutation('1023') # optional - sage.groups + sage: _palp_convert_permutation('1023') # needs sage.groups (1,2) - sage: _palp_convert_permutation('0123456789bac') # optional - sage.groups + sage: _palp_convert_permutation('0123456789bac') # needs sage.groups (11,12) """ def from_palp_index(i): @@ -5271,14 +5284,14 @@ def _read_nef_x_partitions(data): TESTS:: sage: o = lattice_polytope.cross_polytope(3) - sage: s = o.nef_x("-N -p") # optional - palp - sage: print(s) # random # optional - palp + sage: s = o.nef_x("-N -p") # needs palp + sage: print(s) # random # needs palp M:27 8 N:7 6 codim=2 #part=5 P:0 V:2 4 5 0sec 0cpu P:2 V:3 4 5 0sec 0cpu P:3 V:4 5 0sec 0cpu np=3 d:1 p:1 0sec 0cpu - sage: lattice_polytope._read_nef_x_partitions(s) # optional - palp + sage: lattice_polytope._read_nef_x_partitions(s) # needs palp [[2, 4, 5], [3, 4, 5], [4, 5]] """ if isinstance(data, str): @@ -5333,9 +5346,10 @@ def _read_poly_x_incidences(data, dim): TESTS:: + sage: # needs palp sage: p = lattice_polytope.cross_polytope(2) - sage: result_name = lattice_polytope._palp("poly.x -fi", [p]) # optional - palp - sage: with open(result_name) as f: # optional - palp + sage: result_name = lattice_polytope._palp("poly.x -fi", [p]) + sage: with open(result_name) as f: ....: print(f.read()) Incidences as binary numbers [F-vector=(4 4)]: v[d][i]: sum_j Incidence(i'th dim-d-face, j-th vertex) x 2^j @@ -5344,12 +5358,12 @@ def _read_poly_x_incidences(data, dim): f[d][i]: sum_j Incidence(i'th dim-d-face, j-th facet) x 2^j f[0]: 0011 0101 1010 1100 f[1]: 0001 0010 0100 1000 - sage: f = open(result_name) # optional - palp - sage: l = f.readline() # optional - palp - sage: lattice_polytope._read_poly_x_incidences(f, 2) # optional - palp + sage: f = open(result_name) + sage: l = f.readline() + sage: lattice_polytope._read_poly_x_incidences(f, 2) [[[3], [0], [2], [1]], [[0, 3], [2, 3], [0, 1], [1, 2]]] - sage: f.close() # optional - palp - sage: os.remove(result_name) # optional - palp + sage: f.close() + sage: os.remove(result_name) """ data.readline() lines = [data.readline().split() for i in range(dim)] @@ -5387,7 +5401,7 @@ def all_cached_data(polytopes): sequences as well:: sage: o = lattice_polytope.cross_polytope(3) - sage: lattice_polytope.all_cached_data([o]) # optional - palp + sage: lattice_polytope.all_cached_data([o]) # needs palp """ all_polars(polytopes) all_points(polytopes) @@ -5418,8 +5432,8 @@ def all_nef_partitions(polytopes, keep_symmetric=False): sequences as well:: sage: o = lattice_polytope.cross_polytope(3) - sage: lattice_polytope.all_nef_partitions([o]) # optional - palp - sage: o.nef_partitions() # optional - palp + sage: lattice_polytope.all_nef_partitions([o]) # needs palp + sage: o.nef_partitions() # needs palp [ Nef-partition {0, 1, 3} ⊔ {2, 4, 5}, Nef-partition {0, 1, 3, 4} ⊔ {2, 5} (direct product), @@ -5432,7 +5446,7 @@ def all_nef_partitions(polytopes, keep_symmetric=False): sage: p = LatticePolytope([(1,0,0), (0,1,0), (0,0,2), ....: (-1,0,0), (0,-1,0), (0,0,-1)]) - sage: lattice_polytope.all_nef_partitions([o, p]) # optional - palp + sage: lattice_polytope.all_nef_partitions([o, p]) # needs palp Traceback (most recent call last): ... ValueError: nef-partitions can be computed for reflexive polytopes only @@ -5467,8 +5481,8 @@ def all_points(polytopes): sequences as well:: sage: o = lattice_polytope.cross_polytope(3) - sage: lattice_polytope.all_points([o]) # optional - palp - sage: o.points() # optional - palp + sage: lattice_polytope.all_points([o]) # needs palp + sage: o.points() # needs palp M( 1, 0, 0), M( 0, 1, 0), M( 0, 0, 1), @@ -5520,8 +5534,8 @@ def all_polars(polytopes): sequences as well:: sage: o = lattice_polytope.cross_polytope(3) - sage: lattice_polytope.all_polars([o]) # optional - palp - sage: o.polar() # optional - palp + sage: lattice_polytope.all_polars([o]) # needs palp + sage: o.polar() # needs palp 3-d reflexive polytope in 3-d lattice N """ result_name = _palp("poly.x -fe", polytopes) @@ -5663,7 +5677,7 @@ def positive_integer_relations(points): sage: p = LatticePolytope([(1,0,0), (0,1,0), ....: (-1,-1,0), (0,0,1), (-1,0,-1)]) - sage: p.points() # optional - palp + sage: p.points() # needs palp M( 1, 0, 0), M( 0, 1, 0), M(-1, -1, 0), @@ -5675,7 +5689,7 @@ def positive_integer_relations(points): We can compute linear relations between its points in the following way:: - sage: p.points().matrix().kernel().echelonized_basis_matrix() # optional - palp + sage: p.points().matrix().kernel().echelonized_basis_matrix() # needs palp [ 1 0 0 1 1 0] [ 0 1 1 -1 -1 0] [ 0 0 0 0 0 1] @@ -5685,7 +5699,7 @@ def positive_integer_relations(points): coefficients are non-negative integers:: sage: points = p.points().column_matrix() - sage: lattice_polytope.positive_integer_relations(points) # optional - palp + sage: lattice_polytope.positive_integer_relations(points) # needs palp [1 0 0 1 1 0] [1 1 1 0 0 0] [0 0 0 0 0 1] @@ -5751,10 +5765,11 @@ def read_all_polytopes(file_name): We use poly.x to compute two polar polytopes and read them:: + sage: # needs palp sage: d = lattice_polytope.cross_polytope(2) sage: o = lattice_polytope.cross_polytope(3) - sage: result_name = lattice_polytope._palp("poly.x -fe", [d, o]) # optional - palp - sage: with open(result_name) as f: # optional - palp + sage: result_name = lattice_polytope._palp("poly.x -fe", [d, o]) + sage: with open(result_name) as f: ....: print(f.read()) 4 2 Vertices of P-dual <-> Equations of P -1 1 @@ -5770,10 +5785,10 @@ def read_all_polytopes(file_name): 1 -1 -1 -1 1 -1 1 1 -1 - sage: lattice_polytope.read_all_polytopes(result_name) # optional - palp + sage: lattice_polytope.read_all_polytopes(result_name) [2-d reflexive polytope #14 in 2-d lattice M, 3-d reflexive polytope in 3-d lattice M] - sage: os.remove(result_name) # optional - palp + sage: os.remove(result_name) """ polytopes = [] with open(file_name) as f: @@ -5873,7 +5888,7 @@ def set_palp_dimension(d): Let's try to work with a 7-dimensional polytope:: sage: p = lattice_polytope.cross_polytope(7) - sage: p._palp("poly.x -fv") # optional - palp + sage: p._palp("poly.x -fv") # needs palp Traceback (most recent call last): ... ValueError: Error executing 'poly.x -fv' for the given polytope! @@ -5883,7 +5898,7 @@ def set_palp_dimension(d): However, we can work with this polytope by changing PALP dimension to 11:: sage: lattice_polytope.set_palp_dimension(11) - sage: p._palp("poly.x -fv") # optional - palp + sage: p._palp("poly.x -fv") # needs palp '7 14 Vertices of P...' Let's go back to default settings:: @@ -5914,10 +5929,11 @@ def skip_palp_matrix(data, n=1): EXAMPLES: We create a file with vertices of the square and the cube, but read only the second set:: + sage: # needs palp sage: d = lattice_polytope.cross_polytope(2) sage: o = lattice_polytope.cross_polytope(3) - sage: result_name = lattice_polytope._palp("poly.x -fe", [d, o]) # optional - palp - sage: with open(result_name) as f: # optional - palp + sage: result_name = lattice_polytope._palp("poly.x -fe", [d, o]) + sage: with open(result_name) as f: ....: print(f.read()) 4 2 Vertices of P-dual <-> Equations of P -1 1 @@ -5933,14 +5949,14 @@ def skip_palp_matrix(data, n=1): 1 -1 -1 -1 1 -1 1 1 -1 - sage: f = open(result_name) # optional - palp - sage: lattice_polytope.skip_palp_matrix(f) # optional - palp - sage: lattice_polytope.read_palp_matrix(f) # optional - palp + sage: f = open(result_name) + sage: lattice_polytope.skip_palp_matrix(f) + sage: lattice_polytope.read_palp_matrix(f) [-1 1 -1 1 -1 1 -1 1] [-1 -1 1 1 -1 -1 1 1] [ 1 1 1 1 -1 -1 -1 -1] - sage: f.close() # optional - palp - sage: os.remove(result_name) # optional - palp + sage: f.close() + sage: os.remove(result_name) """ for i in range(n): line = data.readline() diff --git a/src/sage/geometry/linear_expression.py b/src/sage/geometry/linear_expression.py index b62e17193a3..0bc15952746 100644 --- a/src/sage/geometry/linear_expression.py +++ b/src/sage/geometry/linear_expression.py @@ -440,7 +440,7 @@ def evaluate(self, point): 9 sage: ex([1,1]) # syntactic sugar 9 - sage: ex([pi, e]) # optional - sage.symbolic + sage: ex([pi, e]) # needs sage.symbolic 2*pi + 3*e + 4 """ try: diff --git a/src/sage/geometry/newton_polygon.py b/src/sage/geometry/newton_polygon.py index 7eae994c6e3..28101e70646 100644 --- a/src/sage/geometry/newton_polygon.py +++ b/src/sage/geometry/newton_polygon.py @@ -464,7 +464,7 @@ def plot(self, **kwargs): sage: from sage.geometry.newton_polygon import NewtonPolygon sage: NP = NewtonPolygon([ (0,0), (1,1), (2,6) ]) - sage: polygon = NP.plot() # optional - sage.plot + sage: polygon = NP.plot() # needs sage.plot """ vertices = self.vertices() if len(vertices) == 0: diff --git a/src/sage/geometry/polyhedral_complex.py b/src/sage/geometry/polyhedral_complex.py index bec18228aca..2e20e508057 100644 --- a/src/sage/geometry/polyhedral_complex.py +++ b/src/sage/geometry/polyhedral_complex.py @@ -203,7 +203,7 @@ class PolyhedralComplex(GenericCellComplex): (A vertex at (0, 1/4),), (A vertex at (1/7, 2/7),), (A vertex at (1/3, 1/3),)] - sage: pc.plot() # optional - sage.plot + sage: pc.plot() # needs sage.plot Graphics object consisting of 10 graphics primitives sage: pc.is_pure() True @@ -752,17 +752,17 @@ def plot(self, **kwds): sage: p3 = Polyhedron(vertices=[(0, 0), (0, 2), (-1, 1)]) sage: pc1 = PolyhedralComplex([p1, p2, p3, -p1, -p2, -p3]) sage: bb = dict(xmin=-2, xmax=2, ymin=-3, ymax=3, axes=False) - sage: g0 = pc1.plot(color='rainbow', **bb) # optional - sage.plot - sage: g1 = pc1.plot(explosion_factor=0.5, **bb) # optional - sage.plot - sage: g2 = pc1.plot(explosion_factor=1, color='rainbow', alpha=0.5, **bb) # optional - sage.plot + sage: g0 = pc1.plot(color='rainbow', **bb) # needs sage.plot + sage: g1 = pc1.plot(explosion_factor=0.5, **bb) # needs sage.plot + sage: g2 = pc1.plot(explosion_factor=1, color='rainbow', alpha=0.5, **bb) # needs sage.plot sage: graphics_array([g0, g1, g2]).show(axes=False) # not tested sage: pc2 = PolyhedralComplex([polytopes.hypercube(3)]) sage: pc3 = pc2.subdivide(new_vertices=[(0, 0, 0)]) - sage: g3 = pc3.plot(explosion_factor=1, color='rainbow', # optional - sage.plot + sage: g3 = pc3.plot(explosion_factor=1, color='rainbow', # needs sage.plot ....: alpha=0.5, axes=False, online=True) sage: pc4 = pc2.subdivide(make_simplicial=True) - sage: g4 = pc4.plot(explosion_factor=1, center=(1, -1, 1), fill='blue', # optional - sage.plot + sage: g4 = pc4.plot(explosion_factor=1, center=(1, -1, 1), fill='blue', # needs sage.plot ....: wireframe='white', point={'color':'red', 'size':10}, ....: alpha=0.6, online=True) sage: pc5 = PolyhedralComplex([ @@ -773,7 +773,7 @@ def plot(self, **kwds): ....: Polyhedron(rays=[[-1,0,0], [0,-1,0], [0,0,1]]), ....: Polyhedron(rays=[[-1,0,0], [0,1,0], [0,0,-1]]), ....: Polyhedron(rays=[[-1,0,0], [0,1,0], [0,0,1]])]) - sage: g5 = pc5.plot(explosion_factor=0.3, color='rainbow', alpha=0.8, # optional - sage.plot + sage: g5 = pc5.plot(explosion_factor=0.3, color='rainbow', alpha=0.8, # needs sage.plot ....: point={'size': 20}, axes=False, online=True) """ @@ -1001,7 +1001,7 @@ def face_poset(self): sage: poset Finite poset containing 11 elements sage: d = {i: i.vertices_matrix() for i in poset} - sage: poset.plot(element_labels=d) # optional - sage.plot + sage: poset.plot(element_labels=d) # needs sage.plot Graphics object consisting of 28 graphics primitives For a nonbounded polyhedral complex:: @@ -2532,11 +2532,11 @@ def exploded_plot(polyhedra, *, sage: p1 = Polyhedron(vertices=[(1, 1), (0, 0), (1, 2)]) sage: p2 = Polyhedron(vertices=[(1, 2), (0, 0), (0, 2)]) sage: p3 = Polyhedron(vertices=[(0, 0), (1, 1), (2, 0)]) - sage: exploded_plot([p1, p2, p3]) # optional - sage.plot + sage: exploded_plot([p1, p2, p3]) # needs sage.plot Graphics object consisting of 20 graphics primitives - sage: exploded_plot([p1, p2, p3], center=(1, 1)) # optional - sage.plot + sage: exploded_plot([p1, p2, p3], center=(1, 1)) # needs sage.plot Graphics object consisting of 19 graphics primitives - sage: exploded_plot([p1, p2, p3], center=(1, 1), sticky_vertices=True) # optional - sage.plot + sage: exploded_plot([p1, p2, p3], center=(1, 1), sticky_vertices=True) # needs sage.plot Graphics object consisting of 23 graphics primitives """ from sage.plot.colors import rainbow diff --git a/src/sage/geometry/polyhedron/backend_cdd_rdf.py b/src/sage/geometry/polyhedron/backend_cdd_rdf.py index ed3f6cac169..a39ad446a80 100644 --- a/src/sage/geometry/polyhedron/backend_cdd_rdf.py +++ b/src/sage/geometry/polyhedron/backend_cdd_rdf.py @@ -134,6 +134,7 @@ def _init_from_Vrepresentation_and_Hrepresentation(self, Vrep, Hrep, verbose=Fal Test that :trac:`29568` is fixed:: + sage: # needs sage.groups sage: P = polytopes.buckyball(exact=False) sage: Q = P + P.center() sage: P.is_combinatorially_isomorphic(Q) diff --git a/src/sage/geometry/polyhedron/backend_field.py b/src/sage/geometry/polyhedron/backend_field.py index 4e190c09cda..77d83c4a381 100644 --- a/src/sage/geometry/polyhedron/backend_field.py +++ b/src/sage/geometry/polyhedron/backend_field.py @@ -7,15 +7,16 @@ EXAMPLES:: + sage: # needs sage.rings.number_field sage: p0 = (0, 0) sage: p1 = (1, 0) - sage: p2 = (1/2, AA(3).sqrt()/2) # optional - sage.rings.number_field - sage: equilateral_triangle = Polyhedron([p0, p1, p2]) # optional - sage.rings.number_field - sage: equilateral_triangle.vertices() # optional - sage.rings.number_field + sage: p2 = (1/2, AA(3).sqrt()/2) + sage: equilateral_triangle = Polyhedron([p0, p1, p2]) + sage: equilateral_triangle.vertices() (A vertex at (0, 0), A vertex at (1, 0), A vertex at (0.500000000000000?, 0.866025403784439?)) - sage: equilateral_triangle.inequalities() # optional - sage.rings.number_field + sage: equilateral_triangle.inequalities() (An inequality (-1, -0.5773502691896258?) x + 1 >= 0, An inequality (1, -0.5773502691896258?) x + 0 >= 0, An inequality (0, 1.154700538379252?) x + 0 >= 0) @@ -46,23 +47,24 @@ class Polyhedron_field(Polyhedron_base): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,0),(AA(2).sqrt(),0),(0,AA(3).sqrt())], # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=[(0,0),(AA(2).sqrt(),0),(0,AA(3).sqrt())], # needs sage.rings.number_field ....: rays=[(1,1)], lines=[], backend='field', base_ring=AA) - sage: TestSuite(p).run() # optional - sage.rings.number_field + sage: TestSuite(p).run() # needs sage.rings.number_field TESTS:: - sage: K. = QuadraticField(3) # optional - sage.rings.number_field - sage: p = Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # optional - sage.rings.number_field - sage: TestSuite(p).run() # optional - sage.rings.number_field + sage: K. = QuadraticField(3) # needs sage.rings.number_field + sage: p = Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # needs sage.rings.number_field + sage: TestSuite(p).run() # needs sage.rings.number_field Check that :trac:`19013` is fixed:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2-x-1, embedding=1.618) # optional - sage.rings.number_field - sage: P1 = Polyhedron([[0,1],[1,1],[1,-phi+1]]) # optional - sage.rings.number_field - sage: P2 = Polyhedron(ieqs=[[-1,-phi,0]]) # optional - sage.rings.number_field - sage: P1.intersection(P2) # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - x - 1, embedding=1.618) + sage: P1 = Polyhedron([[0,1], [1,1], [1,-phi+1]]) + sage: P2 = Polyhedron(ieqs=[[-1,-phi,0]]) + sage: P1.intersection(P2) The empty polyhedron in (Number Field in phi with defining polynomial x^2 - x - 1 with phi = 1.618033988749895?)^2 @@ -85,10 +87,10 @@ def _is_zero(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field - sage: p._is_zero(0) # optional - sage.rings.number_field + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: p._is_zero(0) # needs sage.rings.number_field sage.symbolic True - sage: p._is_zero(1/100000) # optional - sage.rings.number_field + sage: p._is_zero(1/100000) # needs sage.rings.number_fiedl False """ return x == 0 @@ -107,10 +109,10 @@ def _is_nonneg(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field - sage: p._is_nonneg(1) # optional - sage.rings.number_field + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: p._is_nonneg(1) # needs sage.rings.number_field sage.symbolic True - sage: p._is_nonneg(-1/100000) # optional - sage.rings.number_field + sage: p._is_nonneg(-1/100000) # needs sage.rings.number_field sage.symbolic False """ return x >= 0 @@ -129,10 +131,10 @@ def _is_positive(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field - sage: p._is_positive(1) # optional - sage.rings.number_field + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: p._is_positive(1) # needs sage.rings.number_field sage.symbolic True - sage: p._is_positive(0) # optional - sage.rings.number_field + sage: p._is_positive(0) # needs sage.rings.number_field sage.symbolic False """ return x > 0 @@ -152,12 +154,12 @@ def _init_from_Vrepresentation_and_Hrepresentation(self, Vrep, Hrep): sage: from sage.geometry.polyhedron.parent import Polyhedra_field sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field - sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field + sage: parent = Polyhedra_field(AA, 1, 'field') # needs sage.rings.number_field sage: Vrep = [[[0], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field + sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # needs sage.rings.number_field ....: Vrep_minimal=True, Hrep_minimal=True) - sage: p # optional - sage.rings.number_field + sage: p # needs sage.rings.number_field A 1-dimensional polyhedron in AA^1 defined as the convex hull of 2 vertices """ self._init_Vrepresentation(*Vrep) @@ -246,13 +248,13 @@ def _init_Vrepresentation(self, vertices, rays, lines): sage: from sage.geometry.polyhedron.parent import Polyhedra_field sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field - sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field + sage: parent = Polyhedra_field(AA, 1, 'field') # needs sage.rings.number_field sage: Vrep = [[[0], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field + sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # needs sage.rings.number_field ....: Vrep_minimal=True, ....: Hrep_minimal=True) - sage: p.vertices_list() # optional - sage.rings.number_field + sage: p.vertices_list() # needs sage.rings.number_field [[0], [1]] """ self._Vrepresentation = [] @@ -271,15 +273,15 @@ def _init_Vrepresentation_backend(self, Vrep): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0, 1/sqrt(2)), # indirect doctest # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=[(0, 1/sqrt(2)), # indirect doctest # needs sage.rings.number_field sage.symbolic ....: (sqrt(2), 0), ....: (4, sqrt(5)/6)], ....: base_ring=AA, backend='field') - sage: p.Hrepresentation() # optional - sage.rings.number_field + sage: p.Hrepresentation() # needs sage.rings.number_field sage.symbolic (An inequality (-0.1582178750233332?, 1.097777812326429?) x + 0.2237538646678492? >= 0, An inequality (-0.1419794359520263?, -1.698172434277148?) x + 1.200789243901438? >= 0, An inequality (0.3001973109753594?, 0.600394621950719?) x - 0.4245431085692869? >= 0) - sage: p.Vrepresentation() # optional - sage.rings.number_field + sage: p.Vrepresentation() # needs sage.rings.number_field sage.symbolic (A vertex at (0.?e-16, 0.7071067811865475?), A vertex at (1.414213562373095?, 0), A vertex at (4.000000000000000?, 0.372677996249965?)) @@ -294,12 +296,12 @@ def _init_Hrepresentation(self, inequalities, equations): sage: from sage.geometry.polyhedron.parent import Polyhedra_field sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field - sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field + sage: parent = Polyhedra_field(AA, 1, 'field') # needs sage.rings.number_field sage: Vrep = [[[0], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field + sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # needs sage.rings.number_field ....: Vrep_minimal=True, Hrep_minimal=True) - sage: p.inequalities_list() # optional - sage.rings.number_field + sage: p.inequalities_list() # needs sage.rings.number_field [[0, 1], [1, -1]] """ self._Hrepresentation = [] @@ -316,15 +318,15 @@ def _init_Hrepresentation_backend(self, Hrep): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0, 1/sqrt(2)), # indirect doctest # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=[(0, 1/sqrt(2)), # indirect doctest # needs sage.rings.number_field sage.symbolic ....: (sqrt(2), 0), ....: (4, sqrt(5)/6)], ....: base_ring=AA, backend='field') - sage: p.Hrepresentation() # optional - sage.rings.number_field + sage: p.Hrepresentation() # needs sage.rings.number_field sage.symbolic (An inequality (-0.1582178750233332?, 1.097777812326429?) x + 0.2237538646678492? >= 0, An inequality (-0.1419794359520263?, -1.698172434277148?) x + 1.200789243901438? >= 0, An inequality (0.3001973109753594?, 0.600394621950719?) x - 0.4245431085692869? >= 0) - sage: p.Vrepresentation() # optional - sage.rings.number_field + sage: p.Vrepresentation() # needs sage.rings.number_field sage.symbolic (A vertex at (0.?e-16, 0.7071067811865475?), A vertex at (1.414213562373095?, 0), A vertex at (4.000000000000000?, 0.372677996249965?)) @@ -337,11 +339,11 @@ def _init_empty_polyhedron(self): TESTS:: - sage: empty = Polyhedron(backend='field', base_ring=AA); empty # optional - sage.rings.number_field + sage: empty = Polyhedron(backend='field', base_ring=AA); empty # needs sage.rings.number_field The empty polyhedron in AA^0 - sage: empty.Vrepresentation() # optional - sage.rings.number_field + sage: empty.Vrepresentation() # needs sage.rings.number_field () - sage: empty.Hrepresentation() # optional - sage.rings.number_field + sage: empty.Hrepresentation() # needs sage.rings.number_field (An equation -1 == 0,) sage: Polyhedron(vertices=[], backend='field') The empty polyhedron in QQ^0 diff --git a/src/sage/geometry/polyhedron/backend_normaliz.py b/src/sage/geometry/polyhedron/backend_normaliz.py index ce389f090a2..19da8cce5e5 100644 --- a/src/sage/geometry/polyhedron/backend_normaliz.py +++ b/src/sage/geometry/polyhedron/backend_normaliz.py @@ -156,7 +156,7 @@ class Polyhedron_normaliz(Polyhedron_base_number_field): Algebraic polyhedra:: - sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], # optional - sage.rings.number_field sage.symbolic + sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], # needs sage.rings.number_field sage.symbolic ....: backend='normaliz', verbose=True) # ----8<---- Equivalent Normaliz input file ----8<---- amb_space 1 @@ -168,13 +168,13 @@ class Polyhedron_normaliz(Polyhedron_base_number_field): (a) 1 # ----8<-------------------8<-------------------8<---- # Calling PyNormaliz.NmzCone(cone=[], number_field=['a^2 - 2', 'a', '[1.414213562373095 +/- 2.99e-16]'], subspace=[], vertices=[[1, 1], [[[0, 1], [1, 1]], 1]]) - sage: P # optional - sage.rings.number_field sage.symbolic + sage: P # needs sage.rings.number_field sage.symbolic A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.rings.number_field sage.symbolic + sage: P.vertices() # needs sage.rings.number_field sage.symbolic (A vertex at (1), A vertex at (sqrt(2))) - sage: P = polytopes.icosahedron(exact=True, # optional - sage.rings.number_field + sage: P = polytopes.icosahedron(exact=True, # needs sage.rings.number_field ....: backend='normaliz'); P A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 @@ -182,7 +182,7 @@ class Polyhedron_normaliz(Polyhedron_base_number_field): defined as the convex hull of 12 vertices sage: x = polygen(ZZ) - sage: P = Polyhedron(vertices=[[sqrt(2)], # optional - sage.rings.number_field sage.symbolic + sage: P = Polyhedron(vertices=[[sqrt(2)], # needs sage.rings.number_field sage.symbolic ....: [AA.polynomial_root(x^3 - 2, RIF(0,3))]], ....: backend='normaliz', verbose=True) # ----8<---- Equivalent Normaliz input file ----8<---- @@ -195,10 +195,10 @@ class Polyhedron_normaliz(Polyhedron_base_number_field): (a^2) 1 # ----8<-------------------8<-------------------8<---- # Calling PyNormaliz.NmzCone(cone=[], number_field=['a^6 - 2', 'a', '[1.122462048309373 +/- 5.38e-16]'], subspace=[], vertices=[[[[0, 1], [0, 1], [0, 1], [1, 1], [0, 1], [0, 1]], 1], [[[0, 1], [0, 1], [1, 1], [0, 1], [0, 1], [0, 1]], 1]]) - sage: P # optional - sage.rings.number_field sage.symbolic + sage: P # needs sage.rings.number_field sage.symbolic A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.rings.number_field sage.symbolic + sage: P.vertices() # needs sage.rings.number_field sage.symbolic (A vertex at (2^(1/3)), A vertex at (sqrt(2))) """ @@ -248,23 +248,24 @@ def _nmz_result(self, normaliz_cone, property): ... NormalizError: Some error in the normaliz input data detected: Unknown ConeProperty... - sage: x = polygen(QQ, 'x') # optional - sage.rings.number_field - sage: K. = NumberField(x^3 - 3, embedding=AA(3)**(1/3)) # optional - sage.rings.number_field - sage: p = Polyhedron(vertices=[(0, 0), (1, 1), (a, 3), (-1, a**2)], # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: x = polygen(QQ, 'x') + sage: K. = NumberField(x^3 - 3, embedding=AA(3)**(1/3)) + sage: p = Polyhedron(vertices=[(0, 0), (1, 1), (a, 3), (-1, a**2)], ....: rays=[(-1,-a)], backend='normaliz') - sage: sorted(p._nmz_result(p._normaliz_cone, 'VerticesOfPolyhedron')) # optional - sage.rings.number_field + sage: sorted(p._nmz_result(p._normaliz_cone, 'VerticesOfPolyhedron')) [[-1, a^2, 1], [1, 1, 1], [a, 3, 1]] - sage: triangulation_generators = p._nmz_result(p._normaliz_cone, # optional - sage.rings.number_field + sage: triangulation_generators = p._nmz_result(p._normaliz_cone, ....: 'Triangulation')[1] - sage: sorted(triangulation_generators) # optional - sage.rings.number_field + sage: sorted(triangulation_generators) [[-a^2, -3, 0], [-1, a^2, 1], [0, 0, 1], [1, 1, 1], [a, 3, 1]] - sage: p._nmz_result(p._normaliz_cone, 'AffineDim') == 2 # optional - sage.rings.number_field + sage: p._nmz_result(p._normaliz_cone, 'AffineDim') == 2 True - sage: p._nmz_result(p._normaliz_cone, 'EmbeddingDim') == 3 # optional - sage.rings.number_field + sage: p._nmz_result(p._normaliz_cone, 'EmbeddingDim') == 3 True - sage: p._nmz_result(p._normaliz_cone, 'ExtremeRays') # optional - sage.rings.number_field + sage: p._nmz_result(p._normaliz_cone, 'ExtremeRays') [[-1/3*a^2, -1, 0]] - sage: p._nmz_result(p._normaliz_cone, 'MaximalSubspace') # optional - sage.rings.number_field + sage: p._nmz_result(p._normaliz_cone, 'MaximalSubspace') [] """ def rational_handler(list): @@ -309,7 +310,7 @@ def _convert_to_pynormaliz(x): TESTS:: - sage: K. = QuadraticField(2) # optional - sage.rings.number_field + sage: K. = QuadraticField(2) # needs sage.rings.number_field sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz as Pn sage: Pn._convert_to_pynormaliz(17) 17 @@ -321,9 +322,9 @@ def _convert_to_pynormaliz(x): [[28, 5]] sage: Pn._convert_to_pynormaliz(28901824309821093821093812093810928309183091832091/5234573685674784567853456543456456786543456765) [[28901824309821093821093812093810928309183091832091, 5234573685674784567853456543456456786543456765]] - sage: Pn._convert_to_pynormaliz(7 + sqrt2) # optional - sage.rings.number_field + sage: Pn._convert_to_pynormaliz(7 + sqrt2) # needs sage.rings.number_field [[7, 1], [1, 1]] - sage: Pn._convert_to_pynormaliz(7/2 + sqrt2) # optional - sage.rings.number_field + sage: Pn._convert_to_pynormaliz(7/2 + sqrt2) # needs sage.rings.number_field [[7, 2], [1, 1]] sage: Pn._convert_to_pynormaliz([[1, 2], (3, 4)]) [[1, 2], [3, 4]] @@ -331,8 +332,8 @@ def _convert_to_pynormaliz(x): Check that :trac:`29836` is fixed:: sage: P = polytopes.simplex(backend='normaliz') - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: P.dilation(sqrt2) # optional - sage.rings.number_field + sage: K. = QuadraticField(2) # needs sage.rings.number_field + sage: P.dilation(sqrt2) # needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.41...)^4 defined as the convex hull of 4 vertices @@ -367,17 +368,17 @@ def _init_from_normaliz_data(self, data, internal_base_ring=None, verbose=False) [[0, -1, 2], [0, 2, -1]] sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz - sage: from sage.rings.qqbar import AA # optional - sage.rings.number_field - sage: from sage.rings.number_field.number_field import QuadraticField # optional - sage.rings.number_field + sage: from sage.rings.qqbar import AA # needs sage.rings.number_field + sage: from sage.rings.number_field.number_field import QuadraticField # needs sage.rings.number_field sage: data = {'number_field': ['a^2 - 2', 'a', '[1.4 +/- 0.1]'], ....: 'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} sage: from sage.geometry.polyhedron.parent import Polyhedra_normaliz - sage: parent = Polyhedra_normaliz(AA, 2, 'normaliz') # optional - sage.rings.number_field - sage: Polyhedron_normaliz(parent, None, None, # indirect doctest, optional - sage.rings.number_field + sage: parent = Polyhedra_normaliz(AA, 2, 'normaliz') # needs sage.rings.number_field + sage: Polyhedron_normaliz(parent, None, None, # needs sage.rings.number_field ....: normaliz_data=data, ....: internal_base_ring=QuadraticField(2)) A 2-dimensional polyhedron in AA^2 defined as the convex hull of 1 vertex and 2 rays - sage: _.inequalities_list() # optional - sage.rings.number_field + sage: _.inequalities_list() # needs sage.rings.number_field [[0, -1/2, 1], [0, 2, -1]] """ if internal_base_ring is None: @@ -432,10 +433,10 @@ def _is_zero(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field sage.symbolic - sage: p._is_zero(0) # optional - sage.rings.number_field sage.symbolic + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: p._is_zero(0) # needs sage.rings.number_field sage.symbolic True - sage: p._is_zero(1/100000) # optional - sage.rings.number_field sage.symbolic + sage: p._is_zero(1/100000) # needs sage.rings.number_field sage.symbolic False """ return x == 0 @@ -454,10 +455,10 @@ def _is_nonneg(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field sage.symbolic - sage: p._is_nonneg(1) # optional - sage.rings.number_field sage.symbolic + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: p._is_nonneg(1) # needs sage.rings.number_field sage.symbolic True - sage: p._is_nonneg(-1/100000) # optional - sage.rings.number_field sage.symbolic + sage: p._is_nonneg(-1/100000) # needs sage.rings.number_field sage.symbolic False """ return x >= 0 @@ -476,10 +477,10 @@ def _is_positive(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field sage.symbolic - sage: p._is_positive(1) # optional - sage.rings.number_field sage.symbolic + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: p._is_positive(1) # needs sage.rings.number_field sage.symbolic True - sage: p._is_positive(0) # optional - sage.rings.number_field sage.symbolic + sage: p._is_positive(0) # needs sage.rings.number_field sage.symbolic False """ return x > 0 @@ -586,24 +587,25 @@ def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): TESTS:: - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: p = Polyhedron(ieqs=[(1, a, 0)], backend='normaliz') # optional - sage.rings.number_field - sage: p & p == p # optional - sage.rings.number_field + sage: K. = QuadraticField(2) # needs sage.rings.number_field + sage: p = Polyhedron(ieqs=[(1, a, 0)], backend='normaliz') # needs sage.rings.number_field + sage: p & p == p # needs sage.rings.number_field True Check that :trac:`30248` is fixed, that maps as input works:: - sage: q = Polyhedron(backend='normaliz', base_ring=AA, # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: q = Polyhedron(backend='normaliz', base_ring=AA, ....: rays=[(0, 0, 1), (0, 1, -1), (1, 0, -1)]) sage: def make_new_Hrep(h): ....: return tuple(x if i == 0 else -1*x ....: for i, x in enumerate(h._vector)) - sage: new_inequalities = map(make_new_Hrep, q.inequality_generator()) # optional - sage.rings.number_field - sage: new_equations = map(make_new_Hrep, q.equation_generator()) # optional - sage.rings.number_field - sage: parent = q.parent() # optional - sage.rings.number_field - sage: new_q = parent.element_class(parent, None, # optional - sage.rings.number_field + sage: new_inequalities = map(make_new_Hrep, q.inequality_generator()) + sage: new_equations = map(make_new_Hrep, q.equation_generator()) + sage: parent = q.parent() + sage: new_q = parent.element_class(parent, None, ....: [new_inequalities, new_equations]) - sage: new_q # optional - sage.rings.number_field + sage: new_q A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays """ @@ -736,7 +738,7 @@ def _cone_from_Vrepresentation_and_Hrepresentation(self, vertices, rays, lines, ....: for arg in args) sage: test_poly(polytopes.simplex(backend='normaliz')) True - sage: test_poly(polytopes.dodecahedron(backend='normaliz')) # optional - sage.rings.number_field + sage: test_poly(polytopes.dodecahedron(backend='normaliz')) # needs sage.rings.number_field True sage: test_poly(Polyhedron(vertices=[[1,0], [0,1]], rays=[[1,1]], ....: backend='normaliz')) @@ -1022,7 +1024,7 @@ def _number_field_triple(internal_base_ring): sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz as Pn sage: Pn._number_field_triple(QQ) is None True - sage: Pn._number_field_triple(QuadraticField(5)) # optional - sage.rings.number_field + sage: Pn._number_field_triple(QuadraticField(5)) # needs sage.rings.number_field ['a^2 - 5', 'a', '[2.236067977499789 +/- 8.06e-16]'] """ R = internal_base_ring @@ -1271,11 +1273,12 @@ def __setstate__(self, state): sage: P2 == P True - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - sage.rings.number_field - sage: P1 = loads(dumps(P)) # optional - sage.rings.number_field - sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone, # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron(backend='normaliz') + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone, ....: internal_base_ring=P1._internal_base_ring) - sage: P == P2 # optional - sage.rings.number_field + sage: P == P2 True Test that :trac:`31820` is fixed:: @@ -1325,7 +1328,7 @@ def integral_hull(self): sage: P = Polyhedron(ieqs=[[1, 0, 2], [3, 0, -2], [3, 2, -2]], ....: backend='normaliz') sage: PI = P.integral_hull() - sage: P.plot(color='yellow') + PI.plot(color='green') # optional - sage.plot + sage: P.plot(color='yellow') + PI.plot(color='green') # needs sage.plot Graphics object consisting of 10 graphics primitives sage: PI.Vrepresentation() (A vertex at (-1, 0), @@ -1453,8 +1456,8 @@ def _volume_normaliz(self, measure='euclidean'): Check that :trac:`28872` is fixed:: - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - sage.rings.number_field - sage: P.volume(measure='induced_lattice') # optional - sage.rings.number_field + sage: P = polytopes.dodecahedron(backend='normaliz') # needs sage.rings.number_field + sage: P.volume(measure='induced_lattice') # needs sage.rings.number_field -1056*sqrt5 + 2400 Some sanity checks that the ambient volume works correctly:: @@ -1466,12 +1469,12 @@ def _volume_normaliz(self, measure='euclidean'): sage: s._volume_normaliz(measure='ambient') 0 - sage: P = polytopes.regular_polygon(3, backend='normaliz') # optional - sage.rings.number_field - sage: P._volume_normaliz('ambient') == P.volume(engine='internal') # optional - sage.rings.number_field + sage: P = polytopes.regular_polygon(3, backend='normaliz') # needs sage.rings.number_field + sage: P._volume_normaliz('ambient') == P.volume(engine='internal') # needs sage.rings.number_field True - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - sage.rings.number_field - sage: P._volume_normaliz('ambient') == P.volume(engine='internal') # optional - sage.rings.number_field + sage: P = polytopes.dodecahedron(backend='normaliz') # needs sage.rings.number_field + sage: P._volume_normaliz('ambient') == P.volume(engine='internal') # needs sage.rings.number_field True sage: P = Polyhedron(rays=[[1]], backend='normaliz') @@ -1976,9 +1979,9 @@ def integral_points(self, threshold=10000): sage: pts1 = P.integral_points() sage: all(P.contains(p) for p in pts1) True - sage: pts2 = LatticePolytope(v).points() # optional - palp + sage: pts2 = LatticePolytope(v).points() # needs palp sage: for p in pts1: p.set_immutable() - sage: set(pts1) == set(pts2) # optional - palp + sage: set(pts1) == set(pts2) # needs palp True sage: timeit('Polyhedron(v, backend='normaliz').integral_points()') # not tested - random @@ -2238,16 +2241,17 @@ class functions. is equal to 1 = `\chi_{trivial}` (Prop 6.1 [Stap2011]_). Here is the computation for the 3-dimensional standard simplex:: + sage: # needs sage.groups sage: S = polytopes.simplex(3, backend='normaliz'); S A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 4 vertices - sage: G = S.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: G.is_isomorphic(SymmetricGroup(4)) # optional - sage.groups + sage: G = S.restricted_automorphism_group(output='permutation') + sage: G.is_isomorphic(SymmetricGroup(4)) True - sage: len(G) # optional - sage.groups + sage: len(G) 24 - sage: Hstar = S._Hstar_function_normaliz(G); Hstar # optional - sage.groups + sage: Hstar = S._Hstar_function_normaliz(G); Hstar chi_4 - sage: G.character_table() # optional - sage.groups + sage: G.character_table() [ 1 -1 1 1 -1] [ 3 -1 0 -1 1] [ 2 0 -1 2 0] @@ -2259,29 +2263,30 @@ class functions. `\pm(0,0,1),\pm(1,0,1), \pm(0,1,1), \pm(1,1,1)` and let G = `\Zmod{2}` act on P as follows:: + sage: # needs sage.groups sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], [-1,0,-1], ....: [0,1,1], [0,-1,-1], [1,1,1], [-1,-1,-1]], ....: backend='normaliz') - sage: K = P.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: G = K.subgroup(gens=[K([(0,2),(1,3),(4,6),(5,7)])]) # optional - sage.groups - sage: conj_reps = G.conjugacy_classes_representatives() # optional - sage.groups - sage: Dict = P.permutations_to_matrices(conj_reps, acting_group=G) # optional - sage.groups - sage: list(Dict.keys())[0] # optional - sage.groups + sage: K = P.restricted_automorphism_group(output='permutation') + sage: G = K.subgroup(gens=[K([(0,2),(1,3),(4,6),(5,7)])]) + sage: conj_reps = G.conjugacy_classes_representatives() + sage: Dict = P.permutations_to_matrices(conj_reps, acting_group=G) + sage: list(Dict.keys())[0] (0,2)(1,3)(4,6)(5,7) - sage: list(Dict.values())[0] # optional - sage.groups + sage: list(Dict.values())[0] [-1 0 1 0] [ 0 1 0 0] [ 0 0 1 0] [ 0 0 0 1] - sage: len(G) # optional - sage.groups + sage: len(G) 2 - sage: G.character_table() # optional - sage.groups + sage: G.character_table() [ 1 1] [ 1 -1] Then we calculate the rational function `H^*(t)`:: - sage: Hst = P._Hstar_function_normaliz(G); Hst # optional - sage.groups + sage: Hst = P._Hstar_function_normaliz(G); Hst # needs sage.groups (chi_0*t^4 + (3*chi_0 + 3*chi_1)*t^3 + (8*chi_0 + 2*chi_1)*t^2 + (3*chi_0 + 3*chi_1)*t + chi_0)/(t + 1) @@ -2289,7 +2294,7 @@ class functions. ``'Hstar_as_lin_comb'``. The first coordinate is the coefficient of the trivial character; the second is the coefficient of the sign character:: - sage: lin = P._Hstar_function_normaliz(G, output='Hstar_as_lin_comb'); lin # optional - sage.groups + sage: lin = P._Hstar_function_normaliz(G, output='Hstar_as_lin_comb'); lin # needs sage.groups ((t^4 + 3*t^3 + 8*t^2 + 3*t + 1)/(t + 1), (3*t^3 + 2*t^2 + 3*t)/(t + 1)) """ from sage.groups.conjugacy_classes import ConjugacyClassGAP @@ -2400,14 +2405,14 @@ def _Hstar_as_rat_fct(self, initial_Hstar): sage: simplex = Polyhedron(vertices=[[0,0,0], [1,0,0], ....: [0,1,0], [0,0,1]], backend='normaliz') - sage: Hstar = simplex.Hstar_function(); Hstar # indirect doctest # optional - sage.rings.number_field + sage: Hstar = simplex.Hstar_function(); Hstar # indirect doctest # needs sage.rings.number_field chi_4 The polynomial is `\chi_4 \cdot t^0`. We can see which irreducible representation `\chi_4` corresponds to by looking at the character table:: - sage: G = simplex.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: char = G.character_table(); char # optional - sage.groups + sage: G = simplex.restricted_automorphism_group(output='permutation') # needs sage.groups + sage: char = G.character_table(); char # needs sage.groups [ 1 -1 1 1 -1] [ 3 -1 0 -1 1] [ 2 0 -1 2 0] @@ -2421,14 +2426,14 @@ def _Hstar_as_rat_fct(self, initial_Hstar): sage: square = Polyhedron(vertices=[[1,1], [-1,1], [-1,-1], [1,-1]], ....: backend='normaliz') - sage: Hstar = square.Hstar_function(); Hstar # optional - sage.rings.number_field + sage: Hstar = square.Hstar_function(); Hstar # needs sage.rings.number_field chi_0*t^2 + (2*chi_0 + chi_2 + chi_3 + chi_4)*t + chi_0 Plugging in the values from the first column of the character table below yields the `h^*`-polynomial of the square, `t^2+6t+1`:: - sage: G = square.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: G.character_table() # optional - sage.groups + sage: G = square.restricted_automorphism_group(output='permutation') # needs sage.groups + sage: G.character_table() # needs sage.groups [ 1 1 1 1 1] [ 1 -1 -1 1 1] [ 1 -1 1 -1 1] @@ -2475,30 +2480,32 @@ class functions of the acting group. A character `\rho` is effective if The `H^*` series of the two-dimensional permutahedron under the action of the symmetric group is effective:: + sage: # needs sage.groups sage: p3 = polytopes.permutahedron(3, backend='normaliz') - sage: G = p3.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: reflection12 = G([(0,2),(1,4),(3,5)]) # optional - sage.groups - sage: reflection23 = G([(0,1),(2,3),(4,5)]) # optional - sage.groups - sage: S3 = G.subgroup(gens=[reflection12, reflection23]) # optional - sage.groups - sage: S3.is_isomorphic(SymmetricGroup(3)) # optional - sage.groups + sage: G = p3.restricted_automorphism_group(output='permutation') + sage: reflection12 = G([(0,2),(1,4),(3,5)]) + sage: reflection23 = G([(0,1),(2,3),(4,5)]) + sage: S3 = G.subgroup(gens=[reflection12, reflection23]) + sage: S3.is_isomorphic(SymmetricGroup(3)) True - sage: Hstar = p3.Hstar_function(S3) # optional - sage.groups sage.rings.number_field - sage: Hlin = p3.Hstar_function(S3, output='Hstar_as_lin_comb') # optional - sage.groups sage.rings.number_field - sage: p3._is_effective_normaliz(Hstar, Hlin) # optional - sage.groups sage.rings.number_field + sage: Hstar = p3.Hstar_function(S3) # needs sage.rings.number_field + sage: Hlin = p3.Hstar_function(S3, output='Hstar_as_lin_comb') # needs sage.rings.number_field + sage: p3._is_effective_normaliz(Hstar, Hlin) # needs sage.rings.number_field True If the `H^*`-series is not polynomial, then it is not effective:: + sage: # needs sage.groups sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], [-1,0,-1], ....: [0,1,1], [0,-1,-1], [1,1,1], [-1,-1,-1]], ....: backend='normaliz') - sage: G = P.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: H = G.subgroup(gens = [G([(0,2),(1,3),(4,6),(5,7)])]) # optional - sage.groups - sage: Hstar = P.Hstar_function(H); Hstar # optional - sage.groups sage.rings.number_field + sage: G = P.restricted_automorphism_group(output='permutation') + sage: H = G.subgroup(gens = [G([(0,2),(1,3),(4,6),(5,7)])]) + sage: Hstar = P.Hstar_function(H); Hstar # needs sage.rings.number_field (chi_0*t^4 + (3*chi_0 + 3*chi_1)*t^3 + (8*chi_0 + 2*chi_1)*t^2 + (3*chi_0 + 3*chi_1)*t + chi_0)/(t + 1) - sage: Hstar_lin = P.Hstar_function(H, output='Hstar_as_lin_comb') # optional - sage.groups sage.rings.number_field - sage: P._is_effective_normaliz(Hstar, Hstar_lin) # optional - sage.groups sage.rings.number_field + sage: Hstar_lin = P.Hstar_function(H, output='Hstar_as_lin_comb') # needs sage.rings.number_field + sage: P._is_effective_normaliz(Hstar, Hstar_lin) # needs sage.rings.number_field False """ if not Hstar.denominator().is_unit(): diff --git a/src/sage/geometry/polyhedron/backend_number_field.py b/src/sage/geometry/polyhedron/backend_number_field.py index 650c41f1e36..e79688bea5f 100644 --- a/src/sage/geometry/polyhedron/backend_number_field.py +++ b/src/sage/geometry/polyhedron/backend_number_field.py @@ -39,27 +39,26 @@ class Polyhedron_number_field(Polyhedron_field, Polyhedron_base_number_field): EXAMPLES:: - sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], backend='number_field') # optional - sage.rings.number_field - sage: P # optional - sage.rings.number_field + sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], backend='number_field'); P # needs sage.rings.number_field sage.symbolic A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.rings.number_field + sage: P.vertices() # needs sage.rings.number_field sage.symbolic (A vertex at (1), A vertex at (sqrt(2))) - sage: P = polytopes.icosahedron(exact=True, backend='number_field') # optional - sage.rings.number_field - sage: P # optional - sage.rings.number_field + sage: P = polytopes.icosahedron(exact=True, backend='number_field') # needs sage.rings.number_field + sage: P # needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^3 defined as the convex hull of 12 vertices - sage: x = polygen(ZZ); P = Polyhedron( # optional - sage.rings.number_field sage.symbolic + sage: x = polygen(ZZ); P = Polyhedron( # needs sage.rings.number_field sage.symbolic ....: vertices=[[sqrt(2)], [AA.polynomial_root(x^3-2, RIF(0,3))]], ....: backend='number_field') - sage: P # optional - sage.rings.number_field + sage: P # needs sage.rings.number_field sage.symbolic A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.rings.number_field + sage: P.vertices() # needs sage.rings.number_field sage.symbolic (A vertex at (sqrt(2)), A vertex at (2^(1/3))) TESTS: @@ -67,19 +66,21 @@ class Polyhedron_number_field(Polyhedron_field, Polyhedron_base_number_field): Tests from :class:`~sage.geometry.polyhedron.backend_field.Polyhedron_field` -- here the data are already either in a number field or in ``AA``:: - sage: p = Polyhedron(vertices=[(0,0),(AA(2).sqrt(),0),(0,AA(3).sqrt())], # optional - sage.rings.number_field - ....: rays=[(1,1)], lines=[], backend='number_field', base_ring=AA) - sage: TestSuite(p).run() # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=[(0,0),(AA(2).sqrt(),0),(0,AA(3).sqrt())], # needs sage.rings.number_field + ....: rays=[(1,1)], lines=[], backend='number_field', + ....: base_ring=AA) + sage: TestSuite(p).run() # needs sage.rings.number_field - sage: K. = QuadraticField(3) # optional - sage.rings.number_field - sage: p = Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)], backend='number_field') # optional - sage.rings.number_field - sage: TestSuite(p).run() # optional - sage.rings.number_field + sage: K. = QuadraticField(3) # needs sage.rings.number_field + sage: p = Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)], backend='number_field') # needs sage.rings.number_field + sage: TestSuite(p).run() # needs sage.rings.number_field + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 - x - 1, embedding=1.618) # optional - sage.rings.number_field - sage: P1 = Polyhedron([[0,1], [1,1], [1,-phi+1]], backend='number_field') # optional - sage.rings.number_field - sage: P2 = Polyhedron(ieqs=[[-1,-phi,0]], backend='number_field') # optional - sage.rings.number_field - sage: P1.intersection(P2) # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - x - 1, embedding=1.618) + sage: P1 = Polyhedron([[0,1], [1,1], [1,-phi+1]], backend='number_field') + sage: P2 = Polyhedron(ieqs=[[-1,-phi,0]], backend='number_field') + sage: P1.intersection(P2) The empty polyhedron in (Number Field in phi with defining polynomial x^2 - x - 1 with phi = 1.618033988749895?)^2 @@ -120,11 +121,11 @@ def _init_from_Vrepresentation(self, vertices, rays, lines, Check that the coordinates of a vertex get simplified in the Symbolic Ring:: - sage: p = Polyhedron(ambient_dim=2, base_ring=SR, backend='number_field') # optional - sage.symbolic + sage: p = Polyhedron(ambient_dim=2, base_ring=SR, backend='number_field') # needs sage.symbolic sage: from sage.geometry.polyhedron.backend_number_field import Polyhedron_number_field - sage: Polyhedron_number_field._init_from_Vrepresentation(p, [(0,1/2),(sqrt(2),0),(4,5/6)], [], []); p # optional - sage.symbolic + sage: Polyhedron_number_field._init_from_Vrepresentation(p, [(0,1/2),(sqrt(2),0),(4,5/6)], [], []); p # needs sage.symbolic A 2-dimensional polyhedron in (Symbolic Ring)^2 defined as the convex hull of 3 vertices - sage: p.vertices()[0][0] # optional - sage.symbolic + sage: p.vertices()[0][0] 0 """ (vertices, rays, lines), internal_base_ring \ diff --git a/src/sage/geometry/polyhedron/backend_polymake.py b/src/sage/geometry/polyhedron/backend_polymake.py index 52aaeb2743b..624ae2f6340 100644 --- a/src/sage/geometry/polyhedron/backend_polymake.py +++ b/src/sage/geometry/polyhedron/backend_polymake.py @@ -77,13 +77,14 @@ class Polyhedron_polymake(Polyhedron_base): It can also be obtained differently:: - sage: P=Polyhedron(ieqs=[[-2, 1, 1], [-3, -1, -1], [-4, 1, -2]], # optional - jupymake + sage: # optional - jupymake + sage: P=Polyhedron(ieqs=[[-2, 1, 1], [-3, -1, -1], [-4, 1, -2]], ....: backend='polymake') - sage: P # optional - jupymake + sage: P The empty polyhedron in QQ^2 - sage: P.Vrepresentation() # optional - jupymake + sage: P.Vrepresentation() () - sage: P.Hrepresentation() # optional - jupymake + sage: P.Hrepresentation() (An equation -1 == 0,) The full polyhedron:: @@ -96,8 +97,8 @@ class Polyhedron_polymake(Polyhedron_base): Quadratic fields work:: - sage: V = polytopes.dodecahedron().vertices_list() # optional - sage.rings.number_field - sage: Polyhedron(vertices=V, backend='polymake') # optional - jupymake # optional - sage.rings.number_field + sage: V = polytopes.dodecahedron().vertices_list() # needs sage.rings.number_field + sage: Polyhedron(vertices=V, backend='polymake') # optional - jupymake, needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^3 @@ -211,11 +212,12 @@ def __init__(self, parent, Vrep, Hrep, polymake_polytope=None, **kwds): TESTS: - sage: p = Polyhedron(backend='polymake') # optional - jupymake - sage: TestSuite(p).run() # optional - jupymake - sage: p = Polyhedron(vertices=[(1, 1)], rays=[(0, 1)], # optional - jupymake + sage: # optional - jupymake + sage: p = Polyhedron(backend='polymake') + sage: TestSuite(p).run() + sage: p = Polyhedron(vertices=[(1, 1)], rays=[(0, 1)], ....: backend='polymake') - sage: TestSuite(p).run() # optional - jupymake + sage: TestSuite(p).run() We skip the Lawrence test because it involves numerically unstable floating point arithmetic:: @@ -226,14 +228,15 @@ def __init__(self, parent, Vrep, Hrep, polymake_polytope=None, **kwds): :: - sage: p = Polyhedron(rays=[[1,1]], backend='polymake') # optional - jupymake - sage: TestSuite(p).run() # optional - jupymake - sage: p = Polyhedron(rays=[[1]], backend='polymake') # optional - jupymake - sage: TestSuite(p).run() # optional - jupymake - sage: p = Polyhedron(rays=[[1,1,1]], lines=[[1,0,0]], backend='polymake') # optional - jupymake - sage: TestSuite(p).run() # optional - jupymake - sage: p = Polyhedron(vertices=[[]], backend='polymake') # optional - jupymake - sage: TestSuite(p).run() # optional - jupymake + sage: # optional - jupymake + sage: p = Polyhedron(rays=[[1,1]], backend='polymake') + sage: TestSuite(p).run() + sage: p = Polyhedron(rays=[[1]], backend='polymake') + sage: TestSuite(p).run() + sage: p = Polyhedron(rays=[[1,1,1]], lines=[[1,0,0]], backend='polymake') + sage: TestSuite(p).run() + sage: p = Polyhedron(vertices=[[]], backend='polymake') + sage: TestSuite(p).run() """ if polymake_polytope is not None: if Hrep is not None or Vrep is not None: @@ -250,7 +253,7 @@ def _init_from_polymake_polytope(self, polymake_polytope): TESTS:: sage: p = Polyhedron(backend='polymake') # optional - jupymake - sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - jupymake + sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake sage: Polyhedron_polymake._init_from_Hrepresentation(p, [], []) # indirect doctest # optional - jupymake """ self._polymake_polytope = polymake_polytope @@ -281,7 +284,7 @@ def _init_from_Vrepresentation(self, vertices, rays, lines, minimize=True, verbo EXAMPLES:: sage: p = Polyhedron(backend='polymake') # optional - jupymake - sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - jupymake + sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake sage: Polyhedron_polymake._init_from_Vrepresentation(p, [], [], []) # optional - jupymake """ from sage.interfaces.polymake import polymake @@ -348,7 +351,7 @@ def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): EXAMPLES:: sage: p = Polyhedron(backend='polymake') # optional - jupymake - sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - jupymake + sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake sage: Polyhedron_polymake._init_from_Hrepresentation(p, [], []) # optional - jupymake """ from sage.interfaces.polymake import polymake @@ -644,31 +647,35 @@ def __setstate__(self, state): Test that the obtained cone is valid:: - sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake # optional - jupymake - sage: P = polytopes.permutahedron(4, backend='polymake') # optional - jupymake - sage: P1 = loads(dumps(P)) # optional - jupymake - sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) # optional - jupymake - sage: P._test_polymake_pickling(other=P2) # optional - jupymake + sage: # optional - jupymake + sage: from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake + sage: P = polytopes.permutahedron(4, backend='polymake') + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) + sage: P._test_polymake_pickling(other=P2) - sage: P = Polyhedron(lines=[[1,0], [0,1]], backend='polymake') # optional - jupymake - sage: P1 = loads(dumps(P)) # optional - jupymake - sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) # optional - jupymake - sage: P._test_polymake_pickling(other=P2) # optional - jupymake + sage: # optional - jupymake + sage: P = Polyhedron(lines=[[1,0], [0,1]], backend='polymake') + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) + sage: P._test_polymake_pickling(other=P2) sage: P = Polyhedron(backend='polymake') # optional - jupymake sage: P1 = loads(dumps(P)) # optional - jupymake sage: P._test_polymake_pickling(other=P1) # optional - jupymake - sage: P = polytopes.permutahedron(4, backend='polymake') * Polyhedron(lines=[[1]], backend='polymake') # optional - jupymake - sage: P1 = loads(dumps(P)) # optional - jupymake - sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) # optional - jupymake - sage: P._test_polymake_pickling(other=P2) # optional - jupymake + sage: # optional - jupymake + sage: P = polytopes.permutahedron(4, backend='polymake') * Polyhedron(lines=[[1]], backend='polymake') + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) + sage: P._test_polymake_pickling(other=P2) - sage: print("Possible output"); P = polytopes.dodecahedron(backend='polymake') # optional - jupymake # optional - sage.rings.number_field + sage: # optional - jupymake, needs sage.rings.number_field + sage: print("Possible output"); P = polytopes.dodecahedron(backend='polymake') Possible output... - sage: P1 = loads(dumps(P)) # optional - jupymake # optional - sage.rings.number_field - sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) # optional - jupymake # optional - sage.rings.number_field - sage: P._test_polymake_pickling(other=P2) # optional - jupymake # optional - sage.rings.number_field + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_polymake(P1.parent(), None, None, P1._polymake_polytope) + sage: P._test_polymake_pickling(other=P2) """ if "_pickle_vertices" in state[1]: vertices = state[1].pop("_pickle_vertices") diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index ff5be490df5..ec26e49075c 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -124,8 +124,8 @@ class Polyhedron_base(Polyhedron_base7): :: - sage: p = polytopes.flow_polytope(digraphs.DeBruijn(3,2)) # optional - sage.graphs - sage: TestSuite(p).run() # optional - sage.graphs + sage: p = polytopes.flow_polytope(digraphs.DeBruijn(3,2)) # needs sage.combinat sage.graphs + sage: TestSuite(p).run() :: @@ -136,13 +136,13 @@ class Polyhedron_base(Polyhedron_base7): :: sage: P3 = polytopes.permutahedron(3) - sage: P = P3 * Polyhedron(rays=[[0,0,1], [0,1,1], [1,2,3]]) # optional - sage.combinat - sage: TestSuite(P).run() # optional - sage.combinat + sage: P = P3 * Polyhedron(rays=[[0,0,1], [0,1,1], [1,2,3]]) + sage: TestSuite(P).run() :: - sage: P = P3 * Polyhedron(rays=[[0,0,1], [0,1,1]], lines=[[1,0,0]]) # optional - sage.combinat - sage: TestSuite(P).run() # optional - sage.combinat + sage: P = P3 * Polyhedron(rays=[[0,0,1], [0,1,1]], lines=[[1,0,0]]) + sage: TestSuite(P).run() :: @@ -234,44 +234,46 @@ def to_linear_program(self, solver=None, return_variable=False, base_ring=None): Irrational algebraic linear program over an embedded number field:: - sage: p = polytopes.icosahedron() # optional - sage.rings.number_field - sage: lp, x = p.to_linear_program(return_variable=True) # optional - sage.rings.number_field - sage: lp.set_objective(x[0] + x[1] + x[2]) # optional - sage.rings.number_field - sage: lp.solve() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: p = polytopes.icosahedron() + sage: lp, x = p.to_linear_program(return_variable=True) + sage: lp.set_objective(x[0] + x[1] + x[2]) + sage: lp.solve() 1/4*sqrt5 + 3/4 Same example with floating point:: - sage: lp, x = p.to_linear_program(return_variable=True, base_ring=RDF) # optional - sage.rings.number_field - sage: lp.set_objective(x[0] + x[1] + x[2]) # optional - sage.rings.number_field - sage: lp.solve() # tol 1e-5 # optional - sage.rings.number_field + sage: lp, x = p.to_linear_program(return_variable=True, base_ring=RDF) + sage: lp.set_objective(x[0] + x[1] + x[2]) + sage: lp.solve() # tol 1e-5 # needs sage.rings.number_field 1.3090169943749475 Same example with a specific floating point solver:: - sage: lp, x = p.to_linear_program(return_variable=True, solver='GLPK') # optional - sage.rings.number_field - sage: lp.set_objective(x[0] + x[1] + x[2]) # optional - sage.rings.number_field - sage: lp.solve() # tol 1e-8 # optional - sage.rings.number_field + sage: lp, x = p.to_linear_program(return_variable=True, solver='GLPK') + sage: lp.set_objective(x[0] + x[1] + x[2]) + sage: lp.solve() # tol 1e-8 # needs sage.rings.number_field 1.3090169943749475 Irrational algebraic linear program over `AA`:: - sage: p = polytopes.icosahedron(base_ring=AA) # optional - sage.rings.number_field - sage: lp, x = p.to_linear_program(return_variable=True) # optional - sage.rings.number_field - sage: lp.set_objective(x[0] + x[1] + x[2]) # optional - sage.rings.number_field - sage: lp.solve() # long time # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: p = polytopes.icosahedron(base_ring=AA) + sage: lp, x = p.to_linear_program(return_variable=True) + sage: lp.set_objective(x[0] + x[1] + x[2]) + sage: lp.solve() # long time 1.309016994374948? TESTS:: - sage: p = polytopes.flow_polytope(digraphs.DeBruijn(3,2)); p # optional - sage.graphs + sage: p = polytopes.flow_polytope(digraphs.DeBruijn(3,2)); p # needs sage.combinat sage.graphs A 19-dimensional polyhedron in QQ^27 defined as the convex hull of 1 vertex and 148 rays - sage: p.to_linear_program().polyhedron() == p # optional - sage.graphs + sage: p.to_linear_program().polyhedron() == p True - sage: p = polytopes.icosahedron() # optional - sage.rings.number_field - sage: p.to_linear_program(solver='PPL') # optional - sage.rings.number_field + sage: p = polytopes.icosahedron() # needs sage.rings.number_field + sage: p.to_linear_program(solver='PPL') # needs sage.rings.number_field Traceback (most recent call last): ... TypeError: The PPL backend only supports rational data. @@ -317,17 +319,18 @@ def boundary_complex(self): The boundary complex of the octahedron:: + sage: # needs sage.graphs sage: oc = polytopes.octahedron() - sage: sc_oc = oc.boundary_complex() # optional - sage.graphs - sage: fl_oc = oc.face_lattice() # optional - sage.combinat sage.graphs - sage: fl_sc = sc_oc.face_poset() # optional - sage.combinat sage.graphs - sage: [len(x) for x in fl_oc.level_sets()] # optional - sage.combinat sage.graphs + sage: sc_oc = oc.boundary_complex() + sage: fl_oc = oc.face_lattice() # needs sage.combinat + sage: fl_sc = sc_oc.face_poset() # needs sage.combinat + sage: [len(x) for x in fl_oc.level_sets()] # needs sage.combinat [1, 6, 12, 8, 1] - sage: [len(x) for x in fl_sc.level_sets()] # optional - sage.combinat sage.graphs + sage: [len(x) for x in fl_sc.level_sets()] # needs sage.combinat [6, 12, 8] - sage: sc_oc.euler_characteristic() # optional - sage.graphs + sage: sc_oc.euler_characteristic() 2 - sage: sc_oc.homology() # optional - sage.graphs + sage: sc_oc.homology() {0: 0, 1: 0, 2: Z} The polyhedron should be simplicial:: @@ -556,7 +559,7 @@ def is_inscribed(self, certificate=False): sage: V = P.Vrepresentation() sage: H = P.Hrepresentation() sage: parent = P.parent() - sage: for V1 in Permutations(V): # optional - sage.combinat + sage: for V1 in Permutations(V): ....: P1 = parent._element_constructor_( ....: [V1, [], []], [H, []], Vrep_minimal=True, Hrep_minimal=True) ....: assert P1.is_inscribed() @@ -624,7 +627,7 @@ def hyperplane_arrangement(self): EXAMPLES:: sage: p = polytopes.hypercube(2) - sage: p.hyperplane_arrangement() # optional - sage.combinat + sage: p.hyperplane_arrangement() Arrangement <-t0 + 1 | -t1 + 1 | t1 + 1 | t0 + 1> """ names = tuple('t' + str(i) for i in range(self.ambient_dim())) @@ -680,10 +683,10 @@ def normal_fan(self, direction='inner'): ... ValueError: the normal fan is only defined for full-dimensional polytopes - sage: R = Polyhedron(vertices=[[0, 0], # optional - sage.rings.number_field sage.symbolic + sage: R = Polyhedron(vertices=[[0, 0], # needs sage.rings.number_field sage.symbolic ....: [AA(sqrt(2)), 0], ....: [0, AA(sqrt(2))]]) - sage: R.normal_fan() # optional - sage.rings.number_field sage.symbolic + sage: R.normal_fan() # needs sage.rings.number_field sage.symbolic Traceback (most recent call last): ... NotImplementedError: normal fan handles only polytopes over the rationals @@ -764,8 +767,8 @@ def face_fan(self): The polytope has to have rational coordinates:: - sage: S = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: S.face_fan() # optional - sage.rings.number_field + sage: S = polytopes.dodecahedron() # needs sage.rings.number_field + sage: S.face_fan() # needs sage.rings.number_field Traceback (most recent call last): ... NotImplementedError: face fan handles only polytopes over the rationals @@ -856,8 +859,8 @@ def barycentric_subdivision(self, subdivision_frac=None): sage: P.barycentric_subdivision() A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 6 vertices - sage: P = polytopes.regular_polygon(4, base_ring=QQ) # optional - sage.rings.number_field - sage: P.barycentric_subdivision() # optional - sage.rings.number_field + sage: P = polytopes.regular_polygon(4, base_ring=QQ) # needs sage.rings.number_field + sage: P.barycentric_subdivision() # needs sage.rings.number_field A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 8 vertices @@ -969,19 +972,20 @@ def permutations_to_matrices(self, conj_class_reps, acting_group=None, additiona `\pm 1` 2-dimensional square. The permutations are written in terms of the vertices of the square:: - sage: square = Polyhedron(vertices=[[1,1], [-1,1], # optional - pynormaliz + sage: # optional - pynormaliz, needs sage.groups + sage: square = Polyhedron(vertices=[[1,1], [-1,1], ....: [-1,-1], [1,-1]], ....: backend='normaliz') - sage: square.vertices() # optional - pynormaliz + sage: square.vertices() (A vertex at (-1, -1), A vertex at (-1, 1), A vertex at (1, -1), A vertex at (1, 1)) - sage: aut_square = square.restricted_automorphism_group(output='permutation') # optional - pynormaliz sage.groups - sage: conj_reps = aut_square.conjugacy_classes_representatives() # optional - pynormaliz sage.groups - sage: gens_dict = square.permutations_to_matrices(conj_reps) # optional - pynormaliz sage.groups - sage: rotation_180 = aut_square([(0,3),(1,2)]) # optional - pynormaliz sage.groups - sage: rotation_180, gens_dict[rotation_180] # optional - pynormaliz sage.groups + sage: aut_square = square.restricted_automorphism_group(output='permutation') + sage: conj_reps = aut_square.conjugacy_classes_representatives() + sage: gens_dict = square.permutations_to_matrices(conj_reps) + sage: rotation_180 = aut_square([(0,3),(1,2)]) + sage: rotation_180, gens_dict[rotation_180] ( [-1 0 0] [ 0 -1 0] @@ -990,13 +994,14 @@ def permutations_to_matrices(self, conj_class_reps, acting_group=None, additiona This example tests the functionality for additional elements:: + sage: # needs sage.groups sage.rings.real_mpfr sage: C = polytopes.cross_polytope(2) - sage: G = C.restricted_automorphism_group(output='permutation') # optional - sage.groups sage.rings.real_mpfr - sage: conj_reps = G.conjugacy_classes_representatives() # optional - sage.groups sage.rings.real_mpfr - sage: add_elt = G([(0, 2, 3, 1)]) # optional - sage.groups sage.rings.real_mpfr - sage: dict = C.permutations_to_matrices(conj_reps, # optional - sage.groups sage.rings.real_mpfr + sage: G = C.restricted_automorphism_group(output='permutation') + sage: conj_reps = G.conjugacy_classes_representatives() + sage: add_elt = G([(0, 2, 3, 1)]) + sage: dict = C.permutations_to_matrices(conj_reps, ....: additional_elts=[add_elt]) - sage: dict[add_elt] # optional - sage.groups sage.rings.real_mpfr + sage: dict[add_elt] [ 0 1 0] [-1 0 0] [ 0 0 1] @@ -1063,7 +1068,7 @@ def bounding_box(self, integral=False, integral_hull=False): (None, None) sage: Polyhedron([(1/3,2/3), (3/3, 4/3)]).bounding_box(integral_hull=True) ((1, 1), (1, 1)) - sage: polytopes.buckyball(exact=False).bounding_box() # optional - sage.groups + sage: polytopes.buckyball(exact=False).bounding_box() # needs sage.groups ((-0.8090169944, -0.8090169944, -0.8090169944), (0.8090169944, 0.8090169944, 0.8090169944)) @@ -1143,38 +1148,39 @@ def _polymake_init_(self): Non-pointed polyhedron:: + sage: # optional - jupymake sage: P = Polyhedron(vertices=[[1, 0], [0, 1]], lines=[[1, 0]]) - sage: PP = polymake(P) # optional - jupymake - sage: PP.VERTICES # optional - jupymake + sage: PP = polymake(P) + sage: PP.VERTICES 1 0 1 1 0 0 - sage: PP.FACETS # optional - jupymake + sage: PP.FACETS 1 0 -1 0 0 1 - sage: PP.LINEALITY_SPACE # optional - jupymake + sage: PP.LINEALITY_SPACE 0 1 0 Algebraic polyhedron:: - sage: P = polytopes.dodecahedron(); P # optional - sage.rings.number_field + sage: P = polytopes.dodecahedron(); P # needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^3 defined as the convex hull of 20 vertices - sage: print("Maybe recompile warning"); PP = polymake(P); PP # optional - jupymake sage.rings.number_field + sage: print("Maybe recompile warning"); PP = polymake(P); PP # optional - jupymake, needs sage.rings.number_field Maybe recompile warning... Polytope>[...] - sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake sage.rings.number_field + sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake, needs sage.rings.number_field 1 -1+1r5 -4+2r5 0 Floating-point polyhedron:: - sage: P = polytopes.dodecahedron(exact=False); P # optional - sage.groups + sage: P = polytopes.dodecahedron(exact=False); P # needs sage.groups A 3-dimensional polyhedron in RDF^3 defined as the convex hull of 20 vertices - sage: print("Maybe recompile warning"); PP = polymake(P); PP # optional - jupymake sage.groups + sage: print("Maybe recompile warning"); PP = polymake(P); PP # optional - jupymake, needs sage.groups There may be a recompilation warning... Polytope[...] - sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake sage.groups + sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake, needs sage.groups 1 -0.472135955 0 -1.236067978 """ diff --git a/src/sage/geometry/polyhedron/base0.py b/src/sage/geometry/polyhedron/base0.py index 3f6f9d31f7a..556eefc5148 100644 --- a/src/sage/geometry/polyhedron/base0.py +++ b/src/sage/geometry/polyhedron/base0.py @@ -83,10 +83,10 @@ def __init__(self, parent, Vrep, Hrep, Vrep_minimal=None, Hrep_minimal=None, pre sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field sage: from sage.geometry.polyhedron.parent import Polyhedra_field - sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field + sage: parent = Polyhedra_field(AA, 1, 'field') # needs sage.rings.number_field sage: Vrep = [[[0], [1/2], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, # optional - sage.rings.number_field + sage: p = Polyhedron_field(parent, Vrep, Hrep, # needs sage.rings.number_field ....: Vrep_minimal=False, Hrep_minimal=True) Traceback (most recent call last): ... @@ -406,13 +406,13 @@ def change_ring(self, base_ring, backend=None): ... TypeError: cannot change the base ring to the Integer Ring - sage: P = polytopes.regular_polygon(3); P # optional - sage.rings.number_field + sage: P = polytopes.regular_polygon(3); P # needs sage.rings.number_field A 2-dimensional polyhedron in AA^2 defined as the convex hull of 3 vertices - sage: P.vertices() # optional - sage.rings.number_field + sage: P.vertices() # needs sage.rings.number_field (A vertex at (0.?e-16, 1.000000000000000?), A vertex at (0.866025403784439?, -0.500000000000000?), A vertex at (-0.866025403784439?, -0.500000000000000?)) - sage: P.change_ring(QQ) # optional - sage.rings.number_field + sage: P.change_ring(QQ) # needs sage.rings.number_field Traceback (most recent call last): ... TypeError: cannot change the base ring to the Rational Field @@ -425,11 +425,11 @@ def change_ring(self, base_ring, backend=None): base ring from an exact ring into ``RDF`` may cause a loss of data:: - sage: P = Polyhedron([[2/3,0],[6666666666666667/10^16,0]], base_ring=AA); P # optional - sage.rings.number_field + sage: P = Polyhedron([[2/3,0],[6666666666666667/10^16,0]], base_ring=AA); P # needs sage.rings.number_field A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices - sage: Q = P.change_ring(RDF); Q # optional - sage.rings.number_field + sage: Q = P.change_ring(RDF); Q # needs sage.rings.number_field A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex - sage: P.n_vertices() == Q.n_vertices() # optional - sage.rings.number_field + sage: P.n_vertices() == Q.n_vertices() # needs sage.rings.number_field False """ from sage.categories.rings import Rings @@ -577,8 +577,8 @@ def is_compact(self): EXAMPLES:: - sage: p = polytopes.icosahedron() # optional - sage.rings.number_field - sage: p.is_compact() # optional - sage.rings.number_field + sage: p = polytopes.icosahedron() # needs sage.rings.number_field + sage: p.is_compact() # needs sage.rings.number_field True sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0],[0,0,0,1],[1,-1,0,0]]) sage: p.is_compact() @@ -890,11 +890,12 @@ def inequalities(self): An inequality (0, 1, 0) x + 0 >= 0, An inequality (0, 0, 1) x + 0 >= 0) - sage: p3 = Polyhedron(vertices=Permutations([1, 2, 3, 4])) # optional - sage.combinat - sage: ieqs = p3.inequalities() # optional - sage.combinat - sage: ieqs[0] # optional - sage.combinat + sage: # needs sage.combinat + sage: p3 = Polyhedron(vertices=Permutations([1, 2, 3, 4])) + sage: ieqs = p3.inequalities() + sage: ieqs[0] An inequality (0, 1, 1, 1) x - 6 >= 0 - sage: list(_) # optional - sage.combinat + sage: list(_) [-6, 0, 1, 1, 1] """ return tuple(self.inequality_generator()) @@ -915,13 +916,14 @@ def inequalities_list(self): sage: p.inequalities_list()[0:3] [[0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]] - sage: p3 = Polyhedron(vertices=Permutations([1, 2, 3, 4])) # optional - sage.combinat - sage: ieqs = p3.inequalities_list() # optional - sage.combinat - sage: ieqs[0] # optional - sage.combinat + sage: # needs sage.combinat + sage: p3 = Polyhedron(vertices=Permutations([1, 2, 3, 4])) + sage: ieqs = p3.inequalities_list() + sage: ieqs[0] [-6, 0, 1, 1, 1] - sage: ieqs[-1] # optional - sage.combinat + sage: ieqs[-1] [-3, 0, 1, 0, 1] - sage: ieqs == [list(x) for x in p3.inequality_generator()] # optional - sage.combinat + sage: ieqs == [list(x) for x in p3.inequality_generator()] True """ return [list(x) for x in self.inequality_generator()] @@ -1317,8 +1319,8 @@ def backend(self): sage: triangle = Polyhedron(vertices = [[1, 0], [0, 1], [1, 1]]) sage: triangle.backend() 'ppl' - sage: D = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: D.backend() # optional - sage.rings.number_field + sage: D = polytopes.dodecahedron() # needs sage.rings.number_field + sage: D.backend() # needs sage.rings.number_field 'field' sage: P = Polyhedron([[1.23]]) sage: P.backend() @@ -1352,10 +1354,10 @@ def cdd_Hrepresentation(self): end - sage: triangle = Polyhedron(vertices=[[1,0], [0,1], [1,1]], base_ring=AA) # optional - sage.rings.number_field - sage: triangle.base_ring() # optional - sage.rings.number_field + sage: triangle = Polyhedron(vertices=[[1,0], [0,1], [1,1]], base_ring=AA) # needs sage.rings.number_field + sage: triangle.base_ring() # needs sage.rings.number_field Algebraic Real Field - sage: triangle.cdd_Hrepresentation() # optional - sage.rings.number_field + sage: triangle.cdd_Hrepresentation() # needs sage.rings.number_field Traceback (most recent call last): ... TypeError: the base ring must be ZZ, QQ, or RDF diff --git a/src/sage/geometry/polyhedron/base1.py b/src/sage/geometry/polyhedron/base1.py index 9236996fb0a..77b7bf4427e 100644 --- a/src/sage/geometry/polyhedron/base1.py +++ b/src/sage/geometry/polyhedron/base1.py @@ -95,14 +95,15 @@ def __hash__(self): r""" TESTS:: - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: p = Polyhedron(vertices=[(0, 1, a), (3, a, 5)], # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(2) + sage: p = Polyhedron(vertices=[(0, 1, a), (3, a, 5)], ....: rays=[(a, 2, 3), (0, 0, 1)], ....: base_ring=K) - sage: q = Polyhedron(vertices=[(3, a, 5), (0, 1, a)], # optional - sage.rings.number_field + sage: q = Polyhedron(vertices=[(3, a, 5), (0, 1, a)], ....: rays=[(0, 0, 1), (a, 2, 3)], ....: base_ring=K) - sage: hash(p) == hash(q) # optional - sage.rings.number_field + sage: hash(p) == hash(q) True """ # TODO: find something better *but* fast @@ -401,11 +402,11 @@ def ambient_vector_space(self, base_field=None): sage: poly_test.ambient_vector_space() is poly_test.ambient() True - sage: poly_test.ambient_vector_space(AA) # optional - sage.rings.number_field + sage: poly_test.ambient_vector_space(AA) # needs sage.rings.number_field Vector space of dimension 4 over Algebraic Real Field sage: poly_test.ambient_vector_space(RDF) Vector space of dimension 4 over Real Double Field - sage: poly_test.ambient_vector_space(SR) # optional - sage.symbolic + sage: poly_test.ambient_vector_space(SR) # needs sage.symbolic Vector space of dimension 4 over Symbolic Ring """ return self.Vrepresentation_space().vector_space(base_field=base_field) @@ -620,14 +621,15 @@ def contains(self, point): The point need not have coordinates in the same field as the polyhedron:: + sage: # needs sage.symbolic sage: ray = Polyhedron(vertices=[(0,0)], rays=[(1,0)], base_ring=QQ) - sage: ray.contains([sqrt(2)/3,0]) # irrational coordinates are ok # optional - sage.symbolic + sage: ray.contains([sqrt(2)/3,0]) # irrational coordinates are ok True - sage: a = var('a') # optional - sage.symbolic - sage: ray.contains([a,0]) # a might be negative! # optional - sage.symbolic + sage: a = var('a') + sage: ray.contains([a,0]) # a might be negative! False - sage: assume(a>0) # optional - sage.symbolic - sage: ray.contains([a,0]) # optional - sage.symbolic + sage: assume(a>0) + sage: ray.contains([a,0]) True sage: ray.contains(['hello', 'kitty']) # no common ring for coordinates False diff --git a/src/sage/geometry/polyhedron/base2.py b/src/sage/geometry/polyhedron/base2.py index 41ec3ad203d..0594d0c6708 100644 --- a/src/sage/geometry/polyhedron/base2.py +++ b/src/sage/geometry/polyhedron/base2.py @@ -95,7 +95,7 @@ def is_lattice_polytope(self): sage: polytopes.cross_polytope(3).is_lattice_polytope() True - sage: polytopes.regular_polygon(5).is_lattice_polytope() # optional - sage.rings.number_field + sage: polytopes.regular_polygon(5).is_lattice_polytope() # needs sage.rings.number_field False """ if not self.is_compact(): @@ -145,7 +145,7 @@ def lattice_polytope(self, envelope=False): sage: P = Polyhedron(vertices=[(1, 0), (0, 1), (-1, 0), (0, -1)]) sage: lp = P.lattice_polytope(); lp 2-d reflexive polytope... in 2-d lattice M - sage: lp # optional - palp polytopes_db + sage: lp # optional - polytopes_db, needs palp 2-d reflexive polytope #3 in 2-d lattice M sage: lp.vertices() M(-1, 0), @@ -164,7 +164,7 @@ def lattice_polytope(self, envelope=False): to add the argument "envelope=True" to compute an enveloping lattice polytope. sage: lp = P.lattice_polytope(True) - sage: lp # optional - palp polytopes_db + sage: lp # optional - polytopes_db, needs palp 2-d reflexive polytope #5 in 2-d lattice M sage: lp.vertices() M(-1, 0), @@ -208,9 +208,9 @@ def _integral_points_PALP(self): EXAMPLES:: - sage: Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)])._integral_points_PALP() # optional - palp + sage: Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)])._integral_points_PALP() # needs palp [M(-1, -1), M(0, 1), M(1, 0), M(1, 1), M(0, 0)] - sage: Polyhedron(vertices=[(-1/2,-1/2),(1,0),(1,1),(0,1)]).lattice_polytope(True).points() # optional - palp + sage: Polyhedron(vertices=[(-1/2,-1/2),(1,0),(1,1),(0,1)]).lattice_polytope(True).points() # needs palp M(-1, -1), M(-1, 0), M( 0, -1), @@ -219,7 +219,7 @@ def _integral_points_PALP(self): M( 1, 0), M( 0, 0) in 2-d lattice M - sage: Polyhedron(vertices=[(-1/2,-1/2),(1,0),(1,1),(0,1)])._integral_points_PALP() # optional - palp + sage: Polyhedron(vertices=[(-1/2,-1/2),(1,0),(1,1),(0,1)])._integral_points_PALP() # needs palp [M(1, 1), M(0, 1), M(1, 0), M(0, 0)] """ if not self.is_compact(): @@ -263,10 +263,11 @@ def h_star_vector(self): volume = `\frac{1}{dim(S)!}`) is always 1. Here we test this on simplices up to dimension 3:: - sage: s1 = polytopes.simplex(1,backend='normaliz') # optional - pynormaliz - sage: s2 = polytopes.simplex(2,backend='normaliz') # optional - pynormaliz - sage: s3 = polytopes.simplex(3,backend='normaliz') # optional - pynormaliz - sage: [s1.h_star_vector(), s2.h_star_vector(), s3.h_star_vector()] # optional - pynormaliz + sage: # optional - pynormaliz + sage: s1 = polytopes.simplex(1,backend='normaliz') + sage: s2 = polytopes.simplex(2,backend='normaliz') + sage: s3 = polytopes.simplex(3,backend='normaliz') + sage: [s1.h_star_vector(), s2.h_star_vector(), s3.h_star_vector()] [[1], [1], [1]] For a less trivial example, we compute the `h^*`-vector of the @@ -276,8 +277,8 @@ def h_star_vector(self): sage: cube = polytopes.cube(intervals='zero_one', backend='normaliz') # optional - pynormaliz sage: cube.h_star_vector() # optional - pynormaliz [1, 4, 1] - sage: from sage.combinat.combinat import eulerian_number # optional - sage.combinat - sage: [eulerian_number(3,i) for i in range(3)] # optional - sage.combinat + sage: from sage.combinat.combinat import eulerian_number + sage: [eulerian_number(3,i) for i in range(3)] [1, 4, 1] TESTS:: @@ -294,8 +295,8 @@ def h_star_vector(self): ... TypeError: The h_star vector is only defined for lattice polytopes - sage: t2 = Polyhedron(vertices=[[AA(sqrt(2))], [1/2]]) # optional - sage.rings.number_field - sage: t2.h_star_vector() # optional - sage.rings.number_field + sage: t2 = Polyhedron(vertices=[[AA(sqrt(2))], [1/2]]) # needs sage.rings.number_field sage.symbolic + sage: t2.h_star_vector() # needs sage.rings.number_field sage.symbolic Traceback (most recent call last): ... TypeError: The h_star vector is only defined for lattice polytopes @@ -446,9 +447,9 @@ def integral_points(self, threshold=100000): sage: pts1 = P.integral_points() # Sage's own code sage: all(P.contains(p) for p in pts1) True - sage: pts2 = LatticePolytope(v).points() # optional - palp + sage: pts2 = LatticePolytope(v).points() # needs palp sage: for p in pts1: p.set_immutable() - sage: set(pts1) == set(pts2) # optional - palp + sage: set(pts1) == set(pts2) # needs palp True sage: timeit('Polyhedron(v).integral_points()') # not tested - random @@ -642,13 +643,15 @@ def random_integral_point(self, **kwds): EXAMPLES:: sage: P = Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)]) - sage: P.random_integral_point() # random + sage: P.random_integral_point() # random (0, 0) sage: P.random_integral_point() in P.integral_points() True - sage: P.random_integral_point(explicit_enumeration_threshold=0, triangulation='cddlib') # random, optional - latte_int + sage: P.random_integral_point(explicit_enumeration_threshold=0, # random, optional - latte_int + ....: triangulation='cddlib') (1, 1) - sage: P.random_integral_point(explicit_enumeration_threshold=0, triangulation='cddlib', foo=7) # optional - latte_int + sage: P.random_integral_point(explicit_enumeration_threshold=0, # optional - latte_int + ....: triangulation='cddlib', foo=7) Traceback (most recent call last): ... RuntimeError: ... @@ -765,36 +768,37 @@ def generating_function_of_integral_points(self, **kwds): EXAMPLES:: - sage: P2 = ( - ....: Polyhedron(ieqs=[(0, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, -1)]), - ....: Polyhedron(ieqs=[(0, -1, 0, 1), (0, 1, 0, 0), (0, 0, 1, 0)])) - sage: P2[0].generating_function_of_integral_points(sort_factors=True) # optional - sage.combinat + sage: # needs sage.combinat + sage: P2 = (Polyhedron(ieqs=[(0, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, -1)]), + ....: Polyhedron(ieqs=[(0, -1, 0, 1), (0, 1, 0, 0), (0, 0, 1, 0)])) + sage: P2[0].generating_function_of_integral_points(sort_factors=True) 1 * (-y0 + 1)^-1 * (-y1 + 1)^-1 * (-y0*y2 + 1)^-1 - sage: P2[1].generating_function_of_integral_points(sort_factors=True) # optional - sage.combinat + sage: P2[1].generating_function_of_integral_points(sort_factors=True) 1 * (-y1 + 1)^-1 * (-y2 + 1)^-1 * (-y0*y2 + 1)^-1 sage: (P2[0] & P2[1]).Hrepresentation() (An equation (1, 0, -1) x + 0 == 0, An inequality (1, 0, 0) x + 0 >= 0, An inequality (0, 1, 0) x + 0 >= 0) - sage: (P2[0] & P2[1]).generating_function_of_integral_points(sort_factors=True) # optional - sage.combinat + sage: (P2[0] & P2[1]).generating_function_of_integral_points(sort_factors=True) 1 * (-y1 + 1)^-1 * (-y0*y2 + 1)^-1 The number of integer partitions `1 \leq r_0 \leq r_1 \leq r_2 \leq r_3 \leq r_4`:: + sage: # needs sage.combinat sage: P = Polyhedron(ieqs=[(-1, 1, 0, 0, 0, 0), (0, -1, 1, 0, 0, 0), ....: (0, 0, -1, 1, 0, 0), (0, 0, 0, -1, 1, 0), ....: (0, 0, 0, 0, -1, 1)]) - sage: f = P.generating_function_of_integral_points(sort_factors=True); f # optional - sage.combinat + sage: f = P.generating_function_of_integral_points(sort_factors=True); f y0*y1*y2*y3*y4 * (-y4 + 1)^-1 * (-y3*y4 + 1)^-1 * (-y2*y3*y4 + 1)^-1 * (-y1*y2*y3*y4 + 1)^-1 * (-y0*y1*y2*y3*y4 + 1)^-1 - sage: f = f.value() # optional - sage.combinat - sage: P. = PowerSeriesRing(ZZ) # optional - sage.combinat - sage: c = f.subs({y: z for y in f.parent().gens()}); c # optional - sage.combinat + sage: f = f.value() + sage: P. = PowerSeriesRing(ZZ) + sage: c = f.subs({y: z for y in f.parent().gens()}); c z^5 + z^6 + 2*z^7 + 3*z^8 + 5*z^9 + 7*z^10 + 10*z^11 + 13*z^12 + 18*z^13 + 23*z^14 + 30*z^15 + 37*z^16 + 47*z^17 + 57*z^18 + 70*z^19 + 84*z^20 + 101*z^21 + 119*z^22 + 141*z^23 + 164*z^24 + O(z^25) - sage: ([Partitions(k, length=5).cardinality() for k in range(5,20)] == # optional - sage.combinat + sage: ([Partitions(k, length=5).cardinality() for k in range(5,20)] == ....: c.truncate().coefficients(sparse=False)[5:20]) True diff --git a/src/sage/geometry/polyhedron/base3.py b/src/sage/geometry/polyhedron/base3.py index 807714afde3..8904d9fac82 100644 --- a/src/sage/geometry/polyhedron/base3.py +++ b/src/sage/geometry/polyhedron/base3.py @@ -135,8 +135,9 @@ def slack_matrix(self): [1 0 1 0 0 1] [1 0 0 0 1 1] - sage: P = polytopes.dodecahedron().faces(2)[0].as_polyhedron() # optional - sage.rings.number_field - sage: P.slack_matrix() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron().faces(2)[0].as_polyhedron() + sage: P.slack_matrix() [1/2*sqrt5 - 1/2 0 0 1 1/2*sqrt5 - 1/2 0] [ 0 0 1/2*sqrt5 - 1/2 1/2*sqrt5 - 1/2 1 0] [ 0 1/2*sqrt5 - 1/2 1 0 1/2*sqrt5 - 1/2 0] @@ -153,7 +154,7 @@ def slack_matrix(self): sage: Polyhedron().slack_matrix() [] - sage: Polyhedron(base_ring=QuadraticField(2)).slack_matrix().base_ring() # optional - sage.rings.number_field + sage: Polyhedron(base_ring=QuadraticField(2)).slack_matrix().base_ring() # needs sage.rings.number_field Number Field in a with defining polynomial x^2 - 2 with a = 1.41... """ if not self.n_Vrepresentation() or not self.n_Hrepresentation(): @@ -274,7 +275,7 @@ def incidence_matrix(self): sage: P = polytopes.twenty_four_cell() sage: M = P.incidence_matrix() - sage: sum(sum(x) for x in M) == P.flag_f_vector(0, 3) # optional - sage.combinat + sage: sum(sum(x) for x in M) == P.flag_f_vector(0, 3) # needs sage.combinat True TESTS: @@ -287,10 +288,11 @@ def incidence_matrix(self): Test that this method works for inexact base ring (``cdd`` sets the cache already):: - sage: P = polytopes.dodecahedron(exact=False) # optional - sage.groups - sage: M = P.incidence_matrix.cache # optional - sage.groups - sage: P.incidence_matrix.clear_cache() # optional - sage.groups - sage: M == P.incidence_matrix() # optional - sage.groups + sage: # needs sage.groups + sage: P = polytopes.dodecahedron(exact=False) + sage: M = P.incidence_matrix.cache + sage: P.incidence_matrix.clear_cache() + sage: M == P.incidence_matrix() True """ if self.base_ring() in (ZZ, QQ): @@ -1008,8 +1010,8 @@ def vertex_adjacency_matrix(self, algorithm=None): sage: M = Q.vertex_adjacency_matrix() sage: sum(M) (4, 4, 3, 3, 4, 4, 4, 3, 3) - sage: G = Q.vertex_graph() # optional - sage.graphs - sage: G.degree() # optional - sage.graphs + sage: G = Q.vertex_graph() # needs sage.graphs + sage: G.degree() # needs sage.graphs [4, 4, 3, 3, 4, 4, 4, 3, 3] TESTS: @@ -1154,11 +1156,11 @@ def simplicity(self): EXAMPLES:: - sage: polytopes.hypersimplex(4,2).simplicity() # optional - sage.combinat + sage: polytopes.hypersimplex(4,2).simplicity() 1 - sage: polytopes.hypersimplex(5,2).simplicity() # optional - sage.combinat + sage: polytopes.hypersimplex(5,2).simplicity() 2 - sage: polytopes.hypersimplex(6,2).simplicity() # optional - sage.combinat + sage: polytopes.hypersimplex(6,2).simplicity() 3 sage: polytopes.simplex(3).simplicity() 3 @@ -1207,7 +1209,7 @@ def simpliciality(self): sage: polytopes.cyclic_polytope(10,4).simpliciality() 3 - sage: polytopes.hypersimplex(5,2).simpliciality() # optional - sage.combinat + sage: polytopes.hypersimplex(5,2).simpliciality() 2 sage: polytopes.cross_polytope(4).simpliciality() 3 @@ -1293,8 +1295,8 @@ def is_pyramid(self, certificate=False): True sage: P.is_pyramid(certificate=True) (True, A vertex at (1, 0, 0, 0)) - sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() # optional - sage.rings.number_field - sage: egyptian_pyramid.is_pyramid() # optional - sage.rings.number_field + sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() # needs sage.rings.number_field + sage: egyptian_pyramid.is_pyramid() # needs sage.rings.number_field True sage: Q = polytopes.octahedron() sage: Q.is_pyramid() @@ -1463,13 +1465,13 @@ def is_lawrence_polytope(self): EXAMPLES:: - sage: P = polytopes.hypersimplex(5,2) # optional - sage.combinat - sage: L = P.lawrence_polytope() # optional - sage.combinat - sage: L.is_lattice_polytope() # optional - sage.combinat + sage: P = polytopes.hypersimplex(5,2) + sage: L = P.lawrence_polytope() + sage: L.is_lattice_polytope() True - sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() # optional - sage.number_field - sage: egyptian_pyramid.is_lawrence_polytope() # optional - sage.number_field + sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() # needs sage.number_field + sage: egyptian_pyramid.is_lawrence_polytope() # needs sage.number_field True sage: polytopes.octahedron().is_lawrence_polytope() diff --git a/src/sage/geometry/polyhedron/base5.py b/src/sage/geometry/polyhedron/base5.py index 906334eda3d..89feb2d7b0f 100644 --- a/src/sage/geometry/polyhedron/base5.py +++ b/src/sage/geometry/polyhedron/base5.py @@ -324,7 +324,7 @@ def _test_pyramid(self, tester=None, **options): TESTS: - sage: polytopes.regular_polygon(4)._test_pyramid() # optional - sage.rings.number_field + sage: polytopes.regular_polygon(4)._test_pyramid() # needs sage.rings.number_field """ if tester is None: tester = self._tester(**options) @@ -1057,7 +1057,7 @@ def join(self, other): sage: C = polytopes.hypercube(5) sage: S = Polyhedron([[1]]) - sage: C.join(S).is_combinatorially_isomorphic(C.pyramid()) # optional - sage.graphs + sage: C.join(S).is_combinatorially_isomorphic(C.pyramid()) # needs sage.graphs True sage: P = polytopes.simplex(backend='cdd') @@ -1355,10 +1355,11 @@ def intersection(self, other): Check that :trac:`19012` is fixed:: - sage: K. = QuadraticField(5) # optional - sage.rings.number_field - sage: P = Polyhedron([[0, 0], [0, a], [1, 1]]) # optional - sage.rings.number_field - sage: Q = Polyhedron(ieqs=[[-1, a, 1]]) # optional - sage.rings.number_field - sage: P.intersection(Q) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(5) + sage: P = Polyhedron([[0, 0], [0, a], [1, 1]]) + sage: Q = Polyhedron(ieqs=[[-1, a, 1]]) + sage: P.intersection(Q) A 2-dimensional polyhedron in (Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790?)^2 defined as the convex hull of 4 vertices @@ -1712,23 +1713,25 @@ def linear_transformation(self, linear_transf, new_base_ring=None): sage: b3_proj = proj_mat * b3; b3_proj A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 5 vertices - sage: square = polytopes.regular_polygon(4) # optional - sage.rings.number_field - sage: square.vertices_list() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: square = polytopes.regular_polygon(4) + sage: square.vertices_list() [[0, -1], [1, 0], [-1, 0], [0, 1]] - sage: transf = matrix([[1,1], [0,1]]) # optional - sage.rings.number_field - sage: sheared = transf * square # optional - sage.rings.number_field - sage: sheared.vertices_list() # optional - sage.rings.number_field + sage: transf = matrix([[1,1], [0,1]]) + sage: sheared = transf * square + sage: sheared.vertices_list() [[-1, -1], [1, 0], [-1, 0], [1, 1]] - sage: sheared == square.linear_transformation(transf) # optional - sage.rings.number_field + sage: sheared == square.linear_transformation(transf) True Specifying the new base ring may avoid coercion failure:: - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: L. = QuadraticField(3) # optional - sage.rings.number_field - sage: P = polytopes.cube()*sqrt2 # optional - sage.rings.number_field - sage: M = matrix([[sqrt3, 0, 0], [0, sqrt3, 0], [0, 0, 1]]) # optional - sage.rings.number_field - sage: P.linear_transformation(M, new_base_ring=K.composite_fields(L)[0]) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(2) + sage: L. = QuadraticField(3) + sage: P = polytopes.cube()*sqrt2 + sage: M = matrix([[sqrt3, 0, 0], [0, sqrt3, 0], [0, 0, 1]]) + sage: P.linear_transformation(M, new_base_ring=K.composite_fields(L)[0]) A 3-dimensional polyhedron in (Number Field in sqrt2sqrt3 with defining polynomial x^4 - 10*x^2 + 1 with sqrt2sqrt3 = 0.3178372451957823?)^3 @@ -1736,7 +1739,7 @@ def linear_transformation(self, linear_transf, new_base_ring=None): Linear transformation without specified new base ring fails in this case:: - sage: M*P # optional - sage.rings.number_field + sage: M*P # needs sage.rings.number_field Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for *: @@ -1760,7 +1763,7 @@ def linear_transformation(self, linear_transf, new_base_ring=None): A 3-dimensional polyhedron in RDF^4 defined as the convex hull of 5 vertices sage: (1/1 * proj_mat) * b3 A 3-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices - sage: (AA(2).sqrt() * proj_mat) * b3 # optional - sage.rings.number_field + sage: (AA(2).sqrt() * proj_mat) * b3 # needs sage.rings.number_field A 3-dimensional polyhedron in AA^4 defined as the convex hull of 5 vertices Check that zero-matrices act correctly:: @@ -2014,7 +2017,7 @@ def face_truncation(self, face, linear_coefficients=None, cut_frac=None): A vertex at (-1/3, 1, 1), A vertex at (-1/3, 1, -1), A vertex at (-1/3, -1, -1)) - sage: face_trunc.face_lattice().is_isomorphic(Cube.face_lattice()) # optional - sage.combinat sage.graphs + sage: face_trunc.face_lattice().is_isomorphic(Cube.face_lattice()) # needs sage.combinat sage.graphs True TESTS: @@ -2113,15 +2116,16 @@ def stack(self, face, position=None): (1, 9, 16, 9, 1) sage: stacked_square_large = cube.stack(square_face, position=10) - sage: hexaprism = polytopes.regular_polygon(6).prism() # optional - sage.rings.number_field - sage: hexaprism.f_vector() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: hexaprism = polytopes.regular_polygon(6).prism() + sage: hexaprism.f_vector() (1, 12, 18, 8, 1) - sage: square_face = hexaprism.faces(2)[2] # optional - sage.rings.number_field - sage: stacked_hexaprism = hexaprism.stack(square_face) # optional - sage.rings.number_field - sage: stacked_hexaprism.f_vector() # optional - sage.rings.number_field + sage: square_face = hexaprism.faces(2)[2] + sage: stacked_hexaprism = hexaprism.stack(square_face) + sage: stacked_hexaprism.f_vector() (1, 13, 22, 11, 1) - sage: hexaprism.stack(square_face, position=4) # optional - sage.rings.number_field + sage: hexaprism.stack(square_face, position=4) # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: the chosen position is too large @@ -2241,17 +2245,18 @@ def wedge(self, face, width=1): EXAMPLES:: - sage: P_4 = polytopes.regular_polygon(4) # optional - sage.rings.number_field - sage: W1 = P_4.wedge(P_4.faces(1)[0]); W1 # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P_4 = polytopes.regular_polygon(4) + sage: W1 = P_4.wedge(P_4.faces(1)[0]); W1 A 3-dimensional polyhedron in AA^3 defined as the convex hull of 6 vertices - sage: triangular_prism = polytopes.regular_polygon(3).prism() # optional - sage.rings.number_field - sage: W1.is_combinatorially_isomorphic(triangular_prism) # optional - sage.graphs sage.rings.number_field + sage: triangular_prism = polytopes.regular_polygon(3).prism() + sage: W1.is_combinatorially_isomorphic(triangular_prism) # needs sage.graphs True - sage: Q = polytopes.hypersimplex(4,2) # optional - sage.combinat - sage: W2 = Q.wedge(Q.faces(2)[7]); W2 # optional - sage.combinat + sage: Q = polytopes.hypersimplex(4,2) + sage: W2 = Q.wedge(Q.faces(2)[7]); W2 A 4-dimensional polyhedron in QQ^5 defined as the convex hull of 9 vertices - sage: W2.vertices() # optional - sage.combinat + sage: W2.vertices() (A vertex at (1, 1, 0, 0, 1), A vertex at (1, 1, 0, 0, -1), A vertex at (1, 0, 1, 0, 1), @@ -2262,9 +2267,9 @@ def wedge(self, face, width=1): A vertex at (0, 1, 1, 0, 0), A vertex at (0, 1, 0, 1, 0)) - sage: W3 = Q.wedge(Q.faces(1)[11]); W3 # optional - sage.combinat + sage: W3 = Q.wedge(Q.faces(1)[11]); W3 A 4-dimensional polyhedron in QQ^5 defined as the convex hull of 10 vertices - sage: W3.vertices() # optional - sage.combinat + sage: W3.vertices() (A vertex at (1, 1, 0, 0, -2), A vertex at (1, 1, 0, 0, 2), A vertex at (1, 0, 1, 0, -2), @@ -2277,9 +2282,9 @@ def wedge(self, face, width=1): A vertex at (0, 1, 1, 0, -1)) sage: C_3_7 = polytopes.cyclic_polytope(3,7) - sage: P_6 = polytopes.regular_polygon(6) # optional - sage.rings.number_field - sage: W4 = P_6.wedge(P_6.faces(1)[0]) # optional - sage.rings.number_field - sage: W4.is_combinatorially_isomorphic(C_3_7.polar()) # optional - sage.graphs sage.rings.number_field + sage: P_6 = polytopes.regular_polygon(6) # needs sage.rings.number_field + sage: W4 = P_6.wedge(P_6.faces(1)[0]) # needs sage.rings.number_field + sage: W4.is_combinatorially_isomorphic(C_3_7.polar()) # needs sage.graphs sage.rings.number_field True REFERENCES: @@ -2363,10 +2368,11 @@ def face_split(self, face): EXAMPLES:: - sage: pentagon = polytopes.regular_polygon(5) # optional - sage.rings.number_field - sage: f = pentagon.faces(1)[0] # optional - sage.rings.number_field - sage: fsplit_pentagon = pentagon.face_split(f) # optional - sage.rings.number_field - sage: fsplit_pentagon.f_vector() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: pentagon = polytopes.regular_polygon(5) + sage: f = pentagon.faces(1)[0] + sage: fsplit_pentagon = pentagon.face_split(f) + sage: fsplit_pentagon.f_vector() (1, 7, 14, 9, 1) TESTS: @@ -2450,7 +2456,7 @@ def _test_lawrence(self, tester=None, **options): Check that :trac:`28725` is fixed:: - sage: polytopes.regular_polygon(3)._test_lawrence() # optional - sage.rings.number_field + sage: polytopes.regular_polygon(3)._test_lawrence() # needs sage.rings.number_field Check that :trac:`30293` is fixed:: @@ -2559,10 +2565,11 @@ def one_point_suspension(self, vertex): sage: ops_cube.f_vector() (1, 9, 24, 24, 9, 1) - sage: pentagon = polytopes.regular_polygon(5) # optional - sage.rings.number_field - sage: v = pentagon.vertices()[0] # optional - sage.rings.number_field - sage: ops_pentagon = pentagon.one_point_suspension(v) # optional - sage.rings.number_field - sage: ops_pentagon.f_vector() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: pentagon = polytopes.regular_polygon(5) + sage: v = pentagon.vertices()[0] + sage: ops_pentagon = pentagon.one_point_suspension(v) + sage: ops_pentagon.f_vector() (1, 6, 12, 8, 1) It works with a polyhedral face as well:: diff --git a/src/sage/geometry/polyhedron/base6.py b/src/sage/geometry/polyhedron/base6.py index e125b5228a0..b9d23daefa1 100644 --- a/src/sage/geometry/polyhedron/base6.py +++ b/src/sage/geometry/polyhedron/base6.py @@ -45,9 +45,9 @@ class Polyhedron_base6(Polyhedron_base5): sage: from sage.geometry.polyhedron.base6 import Polyhedron_base6 sage: P = polytopes.cube() - sage: Polyhedron_base6.plot(P) # optional - sage.plot + sage: Polyhedron_base6.plot(P) # needs sage.plot Graphics3d Object - sage: print(Polyhedron_base6.tikz(P, output_type='TikzPicture')) # optional - sage.plot + sage: print(Polyhedron_base6.tikz(P, output_type='TikzPicture')) # needs sage.plot \RequirePackage{luatex85} \documentclass[tikz]{standalone} \begin{document} @@ -130,7 +130,7 @@ class Polyhedron_base6(Polyhedron_base5): \end{document} sage: Q = polytopes.hypercube(4) - sage: Polyhedron_base6.show(Q) # optional - sage.plot + sage: Polyhedron_base6.show(Q) # needs sage.plot sage: Polyhedron_base6.schlegel_projection(Q) The projection of a polyhedron into 3 dimensions @@ -194,55 +194,59 @@ def plot(self, By default, the wireframe is rendered in blue and the fill in green:: - sage: square.plot() # optional - sage.plot + sage: # needs sage.plot + sage: square.plot() Graphics object consisting of 6 graphics primitives - sage: point.plot() # optional - sage.plot + sage: point.plot() Graphics object consisting of 1 graphics primitive - sage: line.plot() # optional - sage.plot + sage: line.plot() Graphics object consisting of 2 graphics primitives - sage: cube.plot() # optional - sage.plot + sage: cube.plot() Graphics3d Object - sage: hypercube.plot() # optional - sage.plot + sage: hypercube.plot() Graphics3d Object Draw the lines in red and nothing else:: - sage: square.plot(point=False, line='red', polygon=False) # optional - sage.plot + sage: # needs sage.plot + sage: square.plot(point=False, line='red', polygon=False) Graphics object consisting of 4 graphics primitives - sage: point.plot(point=False, line='red', polygon=False) # optional - sage.plot + sage: point.plot(point=False, line='red', polygon=False) Graphics object consisting of 0 graphics primitives - sage: line.plot(point=False, line='red', polygon=False) # optional - sage.plot + sage: line.plot(point=False, line='red', polygon=False) Graphics object consisting of 1 graphics primitive - sage: cube.plot(point=False, line='red', polygon=False) # optional - sage.plot + sage: cube.plot(point=False, line='red', polygon=False) Graphics3d Object - sage: hypercube.plot(point=False, line='red', polygon=False) # optional - sage.plot + sage: hypercube.plot(point=False, line='red', polygon=False) Graphics3d Object Draw points in red, no lines, and a blue polygon:: - sage: square.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) # optional - sage.plot + sage: # needs sage.plot + sage: square.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) Graphics object consisting of 2 graphics primitives - sage: point.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) # optional - sage.plot + sage: point.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) Graphics object consisting of 1 graphics primitive - sage: line.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) # optional - sage.plot + sage: line.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) Graphics object consisting of 1 graphics primitive - sage: cube.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) # optional - sage.plot + sage: cube.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) Graphics3d Object - sage: hypercube.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) # optional - sage.plot + sage: hypercube.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) Graphics3d Object If we instead use the ``fill`` and ``wireframe`` options, the coloring depends on the dimension of the object:: - sage: square.plot(fill='green', wireframe='red') # optional - sage.plot + sage: # needs sage.plot + sage: square.plot(fill='green', wireframe='red') Graphics object consisting of 6 graphics primitives - sage: point.plot(fill='green', wireframe='red') # optional - sage.plot + sage: point.plot(fill='green', wireframe='red') Graphics object consisting of 1 graphics primitive - sage: line.plot(fill='green', wireframe='red') # optional - sage.plot + sage: line.plot(fill='green', wireframe='red') Graphics object consisting of 2 graphics primitives - sage: cube.plot(fill='green', wireframe='red') # optional - sage.plot + sage: cube.plot(fill='green', wireframe='red') Graphics3d Object - sage: hypercube.plot(fill='green', wireframe='red') # optional - sage.plot + sage: hypercube.plot(fill='green', wireframe='red') Graphics3d Object It is possible to draw polyhedra up to dimension 4, no matter what the @@ -251,32 +255,32 @@ def plot(self, sage: hcube = polytopes.hypercube(5) sage: facet = hcube.facets()[0].as_polyhedron(); facet A 4-dimensional polyhedron in ZZ^5 defined as the convex hull of 16 vertices - sage: facet.plot() # optional - sage.plot + sage: facet.plot() # needs sage.plot Graphics3d Object For a 3d plot, we may draw the polygons with rainbow colors, using any of the following ways:: - sage: cube.plot(polygon='rainbow') # optional - sage.plot + sage: cube.plot(polygon='rainbow') # needs sage.plot Graphics3d Object - sage: cube.plot(polygon={'color':'rainbow'}) # optional - sage.plot + sage: cube.plot(polygon={'color':'rainbow'}) # needs sage.plot Graphics3d Object - sage: cube.plot(fill='rainbow') # optional - sage.plot + sage: cube.plot(fill='rainbow') # needs sage.plot Graphics3d Object For a 3d plot, the size of a point, the thickness of a line and the width of an arrow are controlled by the respective parameters:: sage: prism = Polyhedron(vertices=[[0,0,0],[1,0,0],[0,1,0]], rays=[[0,0,1]]) - sage: prism.plot(size=20, thickness=30, width=1) # optional - sage.plot + sage: prism.plot(size=20, thickness=30, width=1) # needs sage.plot Graphics3d Object - sage: prism.plot(point={'size':20, 'color':'black'}, # optional - sage.plot + sage: prism.plot(point={'size':20, 'color':'black'}, # needs sage.plot ....: line={'thickness':30, 'width':1, 'color':'black'}, ....: polygon='rainbow') Graphics3d Object TESTS:: - sage: for p in square.plot(): # optional - sage.plot + sage: for p in square.plot(): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) blue Point set defined by 4 point(s) blue Line defined by 2 points @@ -285,18 +289,18 @@ def plot(self, blue Line defined by 2 points green Polygon defined by 4 points - sage: for p in line.plot(): # optional - sage.plot + sage: for p in line.plot(): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) blue Point set defined by 2 point(s) green Line defined by 2 points - sage: for p in point.plot(): # optional - sage.plot + sage: for p in point.plot(): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) green Point set defined by 1 point(s) Draw the lines in red and nothing else:: - sage: for p in square.plot(point=False, line='red', polygon=False): # optional - sage.plot + sage: for p in square.plot(point=False, line='red', polygon=False): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Line defined by 2 points red Line defined by 2 points @@ -305,66 +309,68 @@ def plot(self, Draw vertices in red, no lines, and a blue polygon:: - sage: for p in square.plot(point={'color':'red'}, line=False, polygon=(0,0,1)): # optional - sage.plot + sage: for p in square.plot(point={'color':'red'}, line=False, polygon=(0,0,1)): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Point set defined by 4 point(s) (0, 0, 1) Polygon defined by 4 points - sage: for p in line.plot(point={'color':'red'}, line=False, polygon=(0,0,1)): # optional - sage.plot + sage: for p in line.plot(point={'color':'red'}, line=False, polygon=(0,0,1)): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Point set defined by 2 point(s) - sage: for p in point.plot(point={'color':'red'}, line=False, polygon=(0,0,1)): # optional - sage.plot + sage: for p in point.plot(point={'color':'red'}, line=False, polygon=(0,0,1)): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Point set defined by 1 point(s) Draw in red without wireframe:: - sage: for p in square.plot(wireframe=False, fill="red"): # optional - sage.plot + sage: for p in square.plot(wireframe=False, fill="red"): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Polygon defined by 4 points - sage: for p in line.plot(wireframe=False, fill="red"): # optional - sage.plot + sage: for p in line.plot(wireframe=False, fill="red"): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Line defined by 2 points - sage: for p in point.plot(wireframe=False, fill="red"): # optional - sage.plot + sage: for p in point.plot(wireframe=False, fill="red"): # needs sage.plot ....: print("{} {}".format(p.options()['rgbcolor'], p)) red Point set defined by 1 point(s) We try to draw the polytope in 2 or 3 dimensions:: - sage: type(Polyhedron(ieqs=[(1,)]).plot()) # optional - sage.plot + sage: # needs sage.plot + sage: type(Polyhedron(ieqs=[(1,)]).plot()) - sage: type(polytopes.hypercube(1).plot()) # optional - sage.plot + sage: type(polytopes.hypercube(1).plot()) - sage: type(polytopes.hypercube(2).plot()) # optional - sage.plot + sage: type(polytopes.hypercube(2).plot()) - sage: type(polytopes.hypercube(3).plot()) # optional - sage.plot + sage: type(polytopes.hypercube(3).plot()) In 4d a projection to 3d is used:: - sage: type(polytopes.hypercube(4).plot()) # optional - sage.plot + sage: type(polytopes.hypercube(4).plot()) # needs sage.plot - sage: type(polytopes.hypercube(5).plot()) # optional - sage.plot + sage: type(polytopes.hypercube(5).plot()) Traceback (most recent call last): ... NotImplementedError: plotting of 5-dimensional polyhedra not implemented If the polyhedron is not full-dimensional, the :meth:`affine_hull_projection` is used if necessary:: - sage: type(Polyhedron([(0,), (1,)]).plot()) # optional - sage.plot + sage: # needs sage.plot + sage: type(Polyhedron([(0,), (1,)]).plot()) - sage: type(Polyhedron([(0,0), (1,1)]).plot()) # optional - sage.plot + sage: type(Polyhedron([(0,0), (1,1)]).plot()) - sage: type(Polyhedron([(0,0,0), (1,1,1)]).plot()) # optional - sage.plot + sage: type(Polyhedron([(0,0,0), (1,1,1)]).plot()) - sage: type(Polyhedron([(0,0,0,0), (1,1,1,1)]).plot()) # optional - sage.plot + sage: type(Polyhedron([(0,0,0,0), (1,1,1,1)]).plot()) - sage: type(Polyhedron([(0,0,0,0,0), (1,1,1,1,1)]).plot()) # optional - sage.plot + sage: type(Polyhedron([(0,0,0,0,0), (1,1,1,1,1)]).plot()) - sage: type(Polyhedron([(0,0,0,0), (1,1,1,1), (1,0,0,0)]).plot()) # optional - sage.plot + sage: type(Polyhedron([(0,0,0,0), (1,1,1,1), (1,0,0,0)]).plot()) TESTS: @@ -382,28 +388,29 @@ def plot(self, Check that :trac:`31802` is fixed:: + sage: # needs sage.plot sage: halfspace = Polyhedron(rays=[(0, 0, 1)], lines=[(1, 0, 0), (0, 1, 0)]) sage: len(halfspace.projection().arrows) 5 - sage: halfspace.plot(fill=(0, 1, 0)) # optional - sage.plot + sage: halfspace.plot(fill=(0, 1, 0)) Graphics3d Object sage: fullspace = Polyhedron(lines=[(1, 0, 0), (0, 1, 0), (0, 0, 1)]) sage: len(fullspace.projection().arrows) 6 - sage: fullspace.plot(color=(1, 0, 0), alpha=0.5) # optional - sage.plot + sage: fullspace.plot(color=(1, 0, 0), alpha=0.5) Graphics3d Object sage: cone = Polyhedron(rays=[(1, 0, 0), (0, 1, 0), (0, 0, 1)]) - sage: cone.plot(fill='rainbow', alpha=0.6) # optional - sage.plot + sage: cone.plot(fill='rainbow', alpha=0.6) Graphics3d Object sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0)], rays=[(-1, 1, 0), (1, 1, 0), (0, 0, 1)]) - sage: p.plot(fill='mediumspringgreen', point='red', size=30, width=2) # optional - sage.plot + sage: p.plot(fill='mediumspringgreen', point='red', size=30, width=2) Graphics3d Object sage: cylinder = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0)], lines=[(0, 0, 1)]) - sage: cylinder.plot(fill='red') # check it is not all black # optional - sage.plot + sage: cylinder.plot(fill='red') # check it is not all black # needs sage.plot Graphics3d Object sage: quarter = Polyhedron(rays=[(-1, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)]) - sage: quarter.plot(fill='rainbow') # check it is not all black nor with too many colors # optional - sage.plot + sage: quarter.plot(fill='rainbow') # check it is not all black nor with too many colors # needs sage.plot Graphics3d Object """ def merge_options(*opts): @@ -472,7 +479,7 @@ def show(self, **kwds): EXAMPLES:: sage: square = polytopes.hypercube(2) - sage: square.show(point='red') # optional - sage.plot + sage: square.show(point='red') # needs sage.plot """ self.plot(**kwds).show() @@ -546,9 +553,10 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, EXAMPLES:: + sage: # needs sage.plot sage: co = polytopes.cuboctahedron() - sage: Img = co.tikz([0, 0, 1], 0, output_type='TikzPicture') # optional - sage.plot - sage: Img # optional - sage.plot + sage: Img = co.tikz([0, 0, 1], 0, output_type='TikzPicture') + sage: Img \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -565,7 +573,7 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% \end{tikzpicture} \end{document} - sage: print('\n'.join(Img.content().splitlines()[12:21])) # optional - sage.plot + sage: print('\n'.join(Img.content().splitlines()[12:21])) %% with the command: ._tikz_3d_in_3d and parameters: %% view = [0, 0, 1] %% angle = 0 @@ -575,7 +583,7 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% opacity = 0.8 %% vertex_color = green %% axis = False - sage: print('\n'.join(Img.content().splitlines()[22:26])) # optional - sage.plot + sage: print('\n'.join(Img.content().splitlines()[22:26])) %% Coordinate of the vertices: %% \coordinate (-1.00000, -1.00000, 0.00000) at (-1.00000, -1.00000, 0.00000); @@ -583,9 +591,9 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, When output type is a :class:`sage.misc.latex_standalone.TikzPicture`:: + sage: # needs sage.plot sage: co = polytopes.cuboctahedron() - sage: t = co.tikz([674, 108, -731], 112, output_type='TikzPicture') # optional - sage.plot - sage: t # optional - sage.plot + sage: t = co.tikz([674, 108, -731], 112, output_type='TikzPicture'); t \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -602,7 +610,7 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% \end{tikzpicture} \end{document} - sage: path_to_file = t.pdf() # not tested # optional - sage.plot + sage: path_to_file = t.pdf() # not tested """ return self.projection().tikz(view, angle, scale, @@ -694,8 +702,8 @@ def gale_transform(self): Check that :trac:`29073` is fixed:: - sage: P = polytopes.icosahedron(exact=False) # optional - sage.groups - sage: sum(P.gale_transform()).norm() < 1e-15 # optional - sage.groups + sage: P = polytopes.icosahedron(exact=False) # needs sage.groups + sage: sum(P.gale_transform()).norm() < 1e-15 # needs sage.groups True """ if not self.is_compact(): @@ -786,8 +794,8 @@ def render_solid(self, **kwds): EXAMPLES:: sage: p = polytopes.hypercube(3) - sage: p_solid = p.render_solid(opacity=.7) # optional - sage.plot - sage: type(p_solid) # optional - sage.plot + sage: p_solid = p.render_solid(opacity=.7) # needs sage.plot + sage: type(p_solid) # needs sage.plot """ proj = self.projection() @@ -805,8 +813,8 @@ def render_wireframe(self, **kwds): EXAMPLES:: sage: p = Polyhedron([[1,2,],[1,1],[0,0]]) - sage: p_wireframe = p.render_wireframe() # optional - sage.plot - sage: p_wireframe._objects # optional - sage.plot + sage: p_wireframe = p.render_wireframe() # needs sage.plot + sage: p_wireframe._objects # needs sage.plot [Line defined by 2 points, Line defined by 2 points, Line defined by 2 points] """ proj = self.projection() @@ -855,24 +863,25 @@ def schlegel_projection(self, facet=None, position=None): sage: tfcube.facets()[-1] A 3-dimensional face of a Polyhedron in QQ^4 defined as the convex hull of 8 vertices sage: sp = tfcube.schlegel_projection(tfcube.facets()[-1]) - sage: sp.plot() # optional - sage.plot + sage: sp.plot() # needs sage.plot Graphics3d Object The same truncated cube but see inside the tetrahedral facet:: sage: tfcube.facets()[4] A 3-dimensional face of a Polyhedron in QQ^4 defined as the convex hull of 4 vertices - sage: sp = tfcube.schlegel_projection(tfcube.facets()[4]) # optional - sage.symbolic - sage: sp.plot() # optional - sage.plot sage.symbolic + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4]) # needs sage.symbolic + sage: sp.plot() # needs sage.plot sage.symbolic Graphics3d Object A different values of ``position`` changes the projection:: - sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 1/2) # optional - sage.symbolic - sage: sp.plot() # optional - sage.plot sage.symbolic + sage: # needs sage.symbolic + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 1/2) + sage: sp.plot() # needs sage.plot Graphics3d Object - sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 4) # optional - sage.symbolic - sage: sp.plot() # optional - sage.plot sage.symbolic + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 4) + sage: sp.plot() # needs sage.plot Graphics3d Object A value which is too large give a projection point that sees more than @@ -941,7 +950,7 @@ def _affine_hull_projection(self, *, sage: P1 = Polyhedron(vertices=[[-1, 1], [0, -1], [0, 0], [-1, -1]]) sage: P2 = Polyhedron(vertices=[[1, 1], [1, -1], [0, -1], [0, 0]]) sage: P = P1.intersection(P2) - sage: A, b = P.affine_hull_projection(as_affine_map=True, # optional - sage.rings.number_field + sage: A, b = P.affine_hull_projection(as_affine_map=True, ....: orthonormal=True, extend=True) sage: Polyhedron([(2,3,4)]).affine_hull_projection() @@ -953,7 +962,7 @@ def _affine_hull_projection(self, *, 'field' sage: P = Polyhedron(vertices=[[0,0], [1,0]], backend='field') - sage: P.affine_hull_projection(orthogonal=True, orthonormal=True, # optional - sage.rings.number_field + sage: P.affine_hull_projection(orthogonal=True, orthonormal=True, ....: extend=True).backend() 'field' @@ -968,11 +977,11 @@ def _affine_hull_projection(self, *, sage: P = Polyhedron(V) sage: P.affine_hull_projection() A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 6 vertices - sage: P.affine_hull_projection(orthonormal=True) # optional - sage.symbolic + sage: P.affine_hull_projection(orthonormal=True) # needs sage.symbolic Traceback (most recent call last): ... ValueError: the base ring needs to be extended; try with "extend=True" - sage: P.affine_hull_projection(orthonormal=True, extend=True) # optional - sage.rings.number_field + sage: P.affine_hull_projection(orthonormal=True, extend=True) # needs sage.rings.number_field A 4-dimensional polyhedron in AA^4 defined as the convex hull of 6 vertices """ result = AffineHullProjectionData() @@ -1188,13 +1197,13 @@ def affine_hull_projection(self, A 1-dimensional polyhedron in QQ^1 defined as the convex hull of 2 vertices sage: A.vertices() (A vertex at (0), A vertex at (2)) - sage: A = L.affine_hull_projection(orthonormal=True) # optional - sage.rings.number_field + sage: A = L.affine_hull_projection(orthonormal=True) # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: the base ring needs to be extended; try with "extend=True" - sage: A = L.affine_hull_projection(orthonormal=True, extend=True); A # optional - sage.rings.number_field + sage: A = L.affine_hull_projection(orthonormal=True, extend=True); A # needs sage.rings.number_field A 1-dimensional polyhedron in AA^1 defined as the convex hull of 2 vertices - sage: A.vertices() # optional - sage.rings.number_field + sage: A.vertices() # needs sage.rings.number_field (A vertex at (1.414213562373095?), A vertex at (0.?e-18)) More generally:: @@ -1220,9 +1229,9 @@ def affine_hull_projection(self, A vertex at (2, 0, 0), A vertex at (1, 3/2, 0), A vertex at (1, 1/2, 4/3)) - sage: A = S.affine_hull_projection(orthonormal=True, extend=True); A # optional - sage.rings.number_field + sage: A = S.affine_hull_projection(orthonormal=True, extend=True); A # needs sage.rings.number_field A 3-dimensional polyhedron in AA^3 defined as the convex hull of 4 vertices - sage: A.vertices() # optional - sage.rings.number_field + sage: A.vertices() # needs sage.rings.number_field (A vertex at (0.7071067811865475?, 0.4082482904638630?, 1.154700538379252?), A vertex at (0.7071067811865475?, 1.224744871391589?, 0.?e-18), A vertex at (1.414213562373095?, 0.?e-18, 0.?e-18), @@ -1230,103 +1239,108 @@ def affine_hull_projection(self, With the parameter ``minimal`` one can get a minimal base ring:: + sage: # needs sage.rings.number_field sage: s = polytopes.simplex(3) - sage: s_AA = s.affine_hull_projection(orthonormal=True, extend=True) # optional - sage.rings.number_field - sage: s_AA.base_ring() # optional - sage.rings.number_field + sage: s_AA = s.affine_hull_projection(orthonormal=True, extend=True) + sage: s_AA.base_ring() Algebraic Real Field - sage: s_full = s.affine_hull_projection(orthonormal=True, extend=True, # optional - sage.rings.number_field + sage: s_full = s.affine_hull_projection(orthonormal=True, extend=True, ....: minimal=True) - sage: s_full.base_ring() # optional - sage.rings.number_field + sage: s_full.base_ring() Number Field in a with defining polynomial y^4 - 4*y^2 + 1 with a = 0.5176380902050415? More examples with the ``orthonormal`` parameter:: - sage: P = polytopes.permutahedron(3); P # optional - sage.combinat sage.rings.number_field + sage: P = polytopes.permutahedron(3); P A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices - sage: set([F.as_polyhedron().affine_hull_projection( # optional - sage.combinat sage.rings.number_field + sage: set([F.as_polyhedron().affine_hull_projection( # needs sage.combinat sage.rings.number_field ....: orthonormal=True, extend=True).volume() ....: for F in P.affine_hull_projection().faces(1)]) == {1, sqrt(AA(2))} True - sage: set([F.as_polyhedron().affine_hull_projection( # optional - sage.combinat sage.rings.number_field + sage: set([F.as_polyhedron().affine_hull_projection( # needs sage.combinat sage.rings.number_field ....: orthonormal=True, extend=True).volume() ....: for F in P.affine_hull_projection( ....: orthonormal=True, extend=True).faces(1)]) == {sqrt(AA(2))} True - sage: D = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: F = D.faces(2)[0].as_polyhedron() # optional - sage.rings.number_field - sage: F.affine_hull_projection(orthogonal=True) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: D = polytopes.dodecahedron() + sage: F = D.faces(2)[0].as_polyhedron() + sage: F.affine_hull_projection(orthogonal=True) A 2-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^2 defined as the convex hull of 5 vertices - sage: F.affine_hull_projection(orthonormal=True, extend=True) # optional - sage.rings.number_field + sage: F.affine_hull_projection(orthonormal=True, extend=True) A 2-dimensional polyhedron in AA^2 defined as the convex hull of 5 vertices - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: P = Polyhedron([2*[K.zero()],2*[sqrt2]]); P # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(2) + sage: P = Polyhedron([2*[K.zero()],2*[sqrt2]]); P A 1-dimensional polyhedron in (Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?)^2 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.rings.number_field + sage: P.vertices() (A vertex at (0, 0), A vertex at (sqrt2, sqrt2)) - sage: A = P.affine_hull_projection(orthonormal=True); A # optional - sage.rings.number_field + sage: A = P.affine_hull_projection(orthonormal=True); A A 1-dimensional polyhedron in (Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?)^1 defined as the convex hull of 2 vertices - sage: A.vertices() # optional - sage.rings.number_field + sage: A.vertices() (A vertex at (0), A vertex at (2)) - sage: K. = QuadraticField(3) # optional - sage.rings.number_field - sage: P = Polyhedron([2*[K.zero()], 2*[sqrt3]]); P # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(3) + sage: P = Polyhedron([2*[K.zero()], 2*[sqrt3]]); P A 1-dimensional polyhedron in (Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)^2 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - sage.rings.number_field + sage: P.vertices() (A vertex at (0, 0), A vertex at (sqrt3, sqrt3)) - sage: A = P.affine_hull_projection(orthonormal=True) # optional - sage.rings.number_field + sage: A = P.affine_hull_projection(orthonormal=True) Traceback (most recent call last): ... ValueError: the base ring needs to be extended; try with "extend=True" - sage: A = P.affine_hull_projection(orthonormal=True, extend=True); A # optional - sage.rings.number_field + sage: A = P.affine_hull_projection(orthonormal=True, extend=True); A A 1-dimensional polyhedron in AA^1 defined as the convex hull of 2 vertices - sage: A.vertices() # optional - sage.rings.number_field + sage: A.vertices() (A vertex at (0), A vertex at (2.449489742783178?)) - sage: sqrt(6).n() # optional - sage.rings.number_field + sage: sqrt(6).n() 2.44948974278318 The affine hull is combinatorially equivalent to the input:: - sage: P.is_combinatorially_isomorphic(P.affine_hull_projection()) # optional - sage.rings.number_field + sage: P.is_combinatorially_isomorphic(P.affine_hull_projection()) # needs sage.rings.number_field True - sage: P.is_combinatorially_isomorphic(P.affine_hull_projection( # optional - sage.rings.number_field + sage: P.is_combinatorially_isomorphic(P.affine_hull_projection( # needs sage.rings.number_field ....: orthogonal=True)) True - sage: P.is_combinatorially_isomorphic(P.affine_hull_projection( # optional - sage.rings.number_field + sage: P.is_combinatorially_isomorphic(P.affine_hull_projection( # needs sage.rings.number_field ....: orthonormal=True, extend=True)) True The ``orthonormal=True`` parameter preserves volumes; it provides an isometric copy of the polyhedron:: - sage: Pentagon = polytopes.dodecahedron().faces(2)[0].as_polyhedron() # optional - sage.rings.number_field - sage: P = Pentagon.affine_hull_projection(orthonormal=True, extend=True) # optional - sage.rings.number_field - sage: _, c= P.is_inscribed(certificate=True) # optional - sage.rings.number_field - sage: c # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: Pentagon = polytopes.dodecahedron().faces(2)[0].as_polyhedron() + sage: P = Pentagon.affine_hull_projection(orthonormal=True, extend=True) + sage: _, c= P.is_inscribed(certificate=True) + sage: c (0.4721359549995794?, 0.6498393924658126?) - sage: circumradius = (c - vector(P.vertices()[0])).norm() # optional - sage.rings.number_field - sage: p = polytopes.regular_polygon(5) # optional - sage.rings.number_field - sage: p.volume() # optional - sage.rings.number_field + sage: circumradius = (c - vector(P.vertices()[0])).norm() + sage: p = polytopes.regular_polygon(5) + sage: p.volume() 2.377641290737884? - sage: P.volume() # optional - sage.rings.number_field + sage: P.volume() 1.53406271079097? - sage: p.volume()*circumradius^2 # optional - sage.rings.number_field + sage: p.volume()*circumradius^2 1.534062710790965? - sage: P.volume() == p.volume()*circumradius^2 # optional - sage.rings.number_field + sage: P.volume() == p.volume()*circumradius^2 True One can also use ``orthogonal`` parameter to calculate volumes; @@ -1334,31 +1348,33 @@ def affine_hull_projection(self, by the square root of the determinant of the linear part of the affine transformation times its transpose:: - sage: Pentagon = polytopes.dodecahedron().faces(2)[0].as_polyhedron() # optional - sage.rings.number_field - sage: Pnormal = Pentagon.affine_hull_projection(orthonormal=True, # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: Pentagon = polytopes.dodecahedron().faces(2)[0].as_polyhedron() + sage: Pnormal = Pentagon.affine_hull_projection(orthonormal=True, ....: extend=True) - sage: Pgonal = Pentagon.affine_hull_projection(orthogonal=True) # optional - sage.rings.number_field - sage: A, b = Pentagon.affine_hull_projection(orthogonal=True, # optional - sage.rings.number_field + sage: Pgonal = Pentagon.affine_hull_projection(orthogonal=True) + sage: A, b = Pentagon.affine_hull_projection(orthogonal=True, ....: as_affine_map=True) - sage: Adet = (A.matrix().transpose()*A.matrix()).det() # optional - sage.rings.number_field - sage: Pnormal.volume() # optional - sage.rings.number_field + sage: Adet = (A.matrix().transpose()*A.matrix()).det() + sage: Pnormal.volume() 1.53406271079097? - sage: Pgonal.volume()/Adet.sqrt(extend=True) # optional - sage.rings.number_field + sage: Pgonal.volume()/Adet.sqrt(extend=True) -80*(55*sqrt(5) - 123)/sqrt(-6368*sqrt(5) + 14240) - sage: Pgonal.volume()/AA(Adet).sqrt().n(digits=20) # optional - sage.rings.number_field + sage: Pgonal.volume()/AA(Adet).sqrt().n(digits=20) 1.5340627107909646813 - sage: AA(Pgonal.volume()^2) == (Pnormal.volume()^2)*AA(Adet) # optional - sage.rings.number_field + sage: AA(Pgonal.volume()^2) == (Pnormal.volume()^2)*AA(Adet) True Another example with ``as_affine_map=True``:: - sage: P = polytopes.permutahedron(4) # optional - sage.combinat sage.rings.number_field - sage: Q = P.affine_hull_projection(orthonormal=True, extend=True) # optional - sage.combinat sage.rings.number_field - sage: A, b = P.affine_hull_projection(orthonormal=True, extend=True, # optional - sage.combinat sage.rings.number_field + sage: # needs sage.combinat sage.rings.number_field + sage: P = polytopes.permutahedron(4) + sage: Q = P.affine_hull_projection(orthonormal=True, extend=True) + sage: A, b = P.affine_hull_projection(orthonormal=True, extend=True, ....: as_affine_map=True) - sage: Q.center() # optional - sage.combinat sage.rings.number_field + sage: Q.center() (0.7071067811865475?, 1.224744871391589?, 1.732050807568878?) - sage: A(P.center()) + b == Q.center() # optional - sage.combinat sage.rings.number_field + sage: A(P.center()) + b == Q.center() True For unbounded, non full-dimensional polyhedra, the ``orthogonal=True`` and ``orthonormal=True`` @@ -1506,8 +1522,8 @@ def _test_affine_hull_projection(self, tester=None, verbose=False, **options): TESTS:: - sage: D = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: D.facets()[0].as_polyhedron()._test_affine_hull_projection() # optional - sage.rings.number_field + sage: D = polytopes.dodecahedron() # needs sage.rings.number_field + sage: D.facets()[0].as_polyhedron()._test_affine_hull_projection() # needs sage.rings.number_field """ if tester is None: tester = self._tester(**options) @@ -1595,48 +1611,50 @@ def affine_hull_manifold(self, name=None, latex_name=None, start_index=0, ambien EXAMPLES:: + sage: # needs sage.symbolic sage: triangle = Polyhedron([(1, 0, 0), (0, 1, 0), (0, 0, 1)]); triangle A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 3 vertices - sage: A = triangle.affine_hull_manifold(name='A'); A # optional - sage.symbolic + sage: A = triangle.affine_hull_manifold(name='A'); A 2-dimensional Riemannian submanifold A embedded in the Euclidean space E^3 - sage: A.embedding().display() # optional - sage.symbolic + sage: A.embedding().display() A → E^3 (x0, x1) ↦ (x, y, z) = (t0 + x0, t0 + x1, t0 - x0 - x1 + 1) - sage: A.embedding().inverse().display() # optional - sage.symbolic + sage: A.embedding().inverse().display() E^3 → A (x, y, z) ↦ (x0, x1) = (x, y) - sage: A.adapted_chart() # optional - sage.symbolic + sage: A.adapted_chart() [Chart (E^3, (x0_E3, x1_E3, t0_E3))] - sage: A.normal().display() # optional - sage.symbolic + sage: A.normal().display() n = 1/3*sqrt(3) e_x + 1/3*sqrt(3) e_y + 1/3*sqrt(3) e_z - sage: A.induced_metric() # Need to call this before volume_form # optional - sage.symbolic + sage: A.induced_metric() # Need to call this before volume_form Riemannian metric gamma on the 2-dimensional Riemannian submanifold A embedded in the Euclidean space E^3 - sage: A.volume_form() # optional - sage.symbolic + sage: A.volume_form() 2-form eps_gamma on the 2-dimensional Riemannian submanifold A embedded in the Euclidean space E^3 Orthogonal version:: - sage: A = triangle.affine_hull_manifold(name='A', orthogonal=True); A # optional - sage.symbolic + sage: A = triangle.affine_hull_manifold(name='A', orthogonal=True); A # needs sage.symbolic 2-dimensional Riemannian submanifold A embedded in the Euclidean space E^3 - sage: A.embedding().display() # optional - sage.symbolic + sage: A.embedding().display() # needs sage.symbolic A → E^3 (x0, x1) ↦ (x, y, z) = (t0 - 1/2*x0 - 1/3*x1 + 1, t0 + 1/2*x0 - 1/3*x1, t0 + 2/3*x1) - sage: A.embedding().inverse().display() # optional - sage.symbolic + sage: A.embedding().inverse().display() # needs sage.symbolic E^3 → A (x, y, z) ↦ (x0, x1) = (-x + y + 1, -1/2*x - 1/2*y + z + 1/2) Arrangement of affine hull of facets:: - sage: D = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: E3 = EuclideanSpace(3) # optional - sage.rings.number_field sage.symbolic - sage: submanifolds = [ # long time # optional - sage.rings.number_field sage.symbolic + sage: # needs sage.rings.number_field sage.symbolic + sage: D = polytopes.dodecahedron() + sage: E3 = EuclideanSpace(3) + sage: submanifolds = [ # long time ....: F.as_polyhedron().affine_hull_manifold(name=f'F{i}', ....: orthogonal=True, ambient_space=E3) ....: for i, F in enumerate(D.facets())] - sage: sum(FM.plot({}, # not tested # long time # optional - sage.symbolic sage.plot sage.rings.number_field + sage: sum(FM.plot({}, # long time, not tested # needs sage.plot ....: srange(-2, 2, 0.1), srange(-2, 2, 0.1), ....: opacity=0.2) ....: for FM in submanifolds) + D.plot() @@ -1646,7 +1664,7 @@ def affine_hull_manifold(self, name=None, latex_name=None, start_index=0, ambien sage: cube = polytopes.cube(); cube A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices - sage: cube.affine_hull_manifold() # optional - sage.symbolic + sage: cube.affine_hull_manifold() # needs sage.symbolic Euclidean space E^3 """ diff --git a/src/sage/geometry/polyhedron/base7.py b/src/sage/geometry/polyhedron/base7.py index ce632e1655d..c1c06b90a28 100644 --- a/src/sage/geometry/polyhedron/base7.py +++ b/src/sage/geometry/polyhedron/base7.py @@ -43,16 +43,17 @@ class Polyhedron_base7(Polyhedron_base6): TESTS:: + sage: # needs sage.combinat sage: from sage.geometry.polyhedron.base7 import Polyhedron_base7 - sage: P = polytopes.associahedron(['A', 3]) # optional - sage.combinat - sage: Polyhedron_base7.centroid(P) # optional - sage.combinat + sage: P = polytopes.associahedron(['A', 3]) + sage: Polyhedron_base7.centroid(P) (81/632, 36/79, 81/632) - sage: Polyhedron_base7.triangulate(P) # optional - sage.combinat + sage: Polyhedron_base7.triangulate(P) (<0,1,2,13>, <0,1,7,13>, <0,2,5,13>, <0,6,7,12>, <0,6,8,13>, <0,6,12,13>, <0,7,12,13>, <1,2,7,12>, <1,2,12,13>, <1,7,12,13>, <2,3,7,12>, <2,3,12,13>, <3,4,7,12>, <3,11,12,13>, <6,8,9,12>, <6,8,12,13>, <6,9,10,12>, <8,9,12,13>) - sage: Polyhedron_base7.volume(P, measure='induced') # optional - sage.combinat + sage: Polyhedron_base7.volume(P, measure='induced') 79/3 """ @cached_method(do_pickle=True) @@ -91,8 +92,8 @@ def centroid(self, engine='auto', **kwds): sage: P.centroid() (1/4, 0, 0) - sage: P = polytopes.associahedron(['A', 2]) # optional - sage.combinat - sage: P.centroid() # optional - sage.combinat + sage: P = polytopes.associahedron(['A', 2]) # needs sage.combinat + sage: P.centroid() # needs sage.combinat (2/21, 2/21) sage: P = polytopes.permutahedron(4, backend='normaliz') # optional - pynormaliz @@ -258,15 +259,16 @@ def triangulate(self, engine='auto', connected=True, fine=False, regular=None, s The normaliz engine can triangulate pointed cones:: - sage: C1 = Polyhedron(rays=[[0,0,1], [1,0,1], # optional - pynormaliz + sage: # optional - pynormaliz + sage: C1 = Polyhedron(rays=[[0,0,1], [1,0,1], ....: [0,1,1], [1,1,1]], ....: backend='normaliz') - sage: C1.triangulate(engine='normaliz') # optional - pynormaliz + sage: C1.triangulate(engine='normaliz') (<0,1,2>, <1,2,3>) - sage: C2 = Polyhedron(rays=[[1,0,1], [0,0,1], # optional - pynormaliz + sage: C2 = Polyhedron(rays=[[1,0,1], [0,0,1], ....: [0,1,1], [1,1,10/9]], ....: backend='normaliz') - sage: C2.triangulate(engine='normaliz') # optional - pynormaliz + sage: C2.triangulate(engine='normaliz') (<0,1,2>, <1,2,3>) They can also be affine cones:: @@ -389,13 +391,14 @@ def _volume_latte(self, verbose=False, algorithm='triangulate', **kwargs): EXAMPLES:: - sage: polytopes.hypercube(3)._volume_latte() # optional - latte_int + sage: # optional - latte_int + sage: polytopes.hypercube(3)._volume_latte() 8 - sage: (polytopes.hypercube(3)*2)._volume_latte() # optional - latte_int + sage: (polytopes.hypercube(3)*2)._volume_latte() 64 - sage: polytopes.twenty_four_cell()._volume_latte() # optional - latte_int + sage: polytopes.twenty_four_cell()._volume_latte() 2 - sage: polytopes.cuboctahedron()._volume_latte() # optional - latte_int + sage: polytopes.cuboctahedron()._volume_latte() 20/3 TESTS: @@ -514,13 +517,13 @@ def volume(self, measure='ambient', engine='auto', **kwds): If the base ring is exact, the answer is exact:: - sage: P5 = polytopes.regular_polygon(5) # optional - sage.rings.number_field - sage: P5.volume() # optional - sage.rings.number_field + sage: P5 = polytopes.regular_polygon(5) # needs sage.rings.number_field + sage: P5.volume() # needs sage.rings.number_field 2.377641290737884? - sage: polytopes.icosahedron().volume() # optional - sage.rings.number_field + sage: polytopes.icosahedron().volume() # needs sage.rings.number_field 5/12*sqrt5 + 5/4 - sage: numerical_approx(_) # abs tol 1e9 # optional - sage.rings.number_field + sage: numerical_approx(_) # abs tol 1e9 # needs sage.rings.number_field 2.18169499062491 When considering lower-dimensional polytopes, we can ask for the @@ -533,36 +536,38 @@ def volume(self, measure='ambient', engine='auto', **kwds): sage: P = Polyhedron([[0, 0], [1, 1]]) sage: P.volume() 0 - sage: P.volume(measure='induced') # optional - sage.rings.number_field + sage: P.volume(measure='induced') # needs sage.rings.number_field 1.414213562373095? sage: P.volume(measure='induced_rational') # optional - latte_int 1 - sage: S = polytopes.regular_polygon(6); S # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: S = polytopes.regular_polygon(6); S A 2-dimensional polyhedron in AA^2 defined as the convex hull of 6 vertices - sage: edge = S.faces(1)[4].as_polyhedron() # optional - sage.rings.number_field - sage: edge.vertices() # optional - sage.rings.number_field + sage: edge = S.faces(1)[4].as_polyhedron() + sage: edge.vertices() (A vertex at (0.866025403784439?, 1/2), A vertex at (0, 1)) - sage: edge.volume() # optional - sage.rings.number_field + sage: edge.volume() 0 - sage: edge.volume(measure='induced') # optional - sage.rings.number_field + sage: edge.volume(measure='induced') 1 - sage: P = Polyhedron(backend='normaliz', # optional - pynormaliz + sage: # optional - pynormaliz + sage: P = Polyhedron(backend='normaliz', ....: vertices=[[1,0,0], [0,0,1], ....: [-1,1,1], [-1,2,0]]) - sage: P.volume() # optional - pynormaliz + sage: P.volume() 0 - sage: P.volume(measure='induced') # optional - pynormaliz sage.rings.number_field + sage: P.volume(measure='induced') # needs sage.rings.number_field 2.598076211353316? - sage: P.volume(measure='induced', engine='normaliz') # optional - pynormaliz + sage: P.volume(measure='induced', engine='normaliz') 2.598076211353316 - sage: P.volume(measure='induced_rational') # optional - pynormaliz latte_int + sage: P.volume(measure='induced_rational') # optional - latte_int 3/2 - sage: P.volume(measure='induced_rational', # optional - pynormaliz + sage: P.volume(measure='induced_rational', ....: engine='normaliz') 3/2 - sage: P.volume(measure='induced_lattice') # optional - pynormaliz + sage: P.volume(measure='induced_lattice') 3 The same polytope without normaliz backend:: @@ -571,35 +576,37 @@ def volume(self, measure='ambient', engine='auto', **kwds): sage: P.volume(measure='induced_lattice', engine='latte') # optional - latte_int 3 - sage: Dexact = polytopes.dodecahedron() # optional - sage.rings.number_field sage.groups + sage: # needs sage.groups sage.rings.number_field + sage: Dexact = polytopes.dodecahedron() sage: F0 = Dexact.faces(2)[0].as_polyhedron() - sage: v = F0.volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field sage.groups + sage: v = F0.volume(measure='induced', engine='internal'); v 1.53406271079097? sage: F4 = Dexact.faces(2)[4].as_polyhedron() - sage: v = F4.volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field sage.groups + sage: v = F4.volume(measure='induced', engine='internal'); v 1.53406271079097? - sage: RDF(v) # abs tol 1e-9 # optional - sage.rings.number_field sage.groups + sage: RDF(v) # abs tol 1e-9 1.53406271079044 - sage: Dinexact = polytopes.dodecahedron(exact=False) # optional - sage.groups + sage: # needs sage.groups + sage: Dinexact = polytopes.dodecahedron(exact=False) sage: F2 = Dinexact.faces(2)[2].as_polyhedron() - sage: w = F2.volume(measure='induced', engine='internal') # optional - sage.groups + sage: w = F2.volume(measure='induced', engine='internal') sage: RDF(w) # abs tol 1e-9 1.5340627082974878 - sage: all(polytopes.simplex(d).volume(measure='induced') # optional - sage.rings.number_field sage.symbolic + sage: all(polytopes.simplex(d).volume(measure='induced') # needs sage.rings.number_field sage.symbolic ....: == sqrt(d+1)/factorial(d) ....: for d in range(1,5)) True sage: I = Polyhedron([[-3, 0], [0, 9]]) - sage: I.volume(measure='induced') # optional - sage.rings.number_field + sage: I.volume(measure='induced') # needs sage.rings.number_field 9.48683298050514? sage: I.volume(measure='induced_rational') # optional - latte_int 3 sage: T = Polyhedron([[3, 0, 0], [0, 4, 0], [0, 0, 5]]) - sage: T.volume(measure='induced') # optional - sage.rings.number_field + sage: T.volume(measure='induced') # needs sage.rings.number_field 13.86542462386205? sage: T.volume(measure='induced_rational') # optional - latte_int 1/2 @@ -628,7 +635,7 @@ def volume(self, measure='ambient', engine='auto', **kwds): 0 sage: P.volume(measure='induced_rational') # optional - pynormaliz +Infinity - sage: P.volume(measure='induced_rational',engine='latte') # optional - latte_int + sage: P.volume(measure='induced_rational',engine='latte') +Infinity The volume in `0`-dimensional space is taken by counting measure:: @@ -809,7 +816,7 @@ def integrate(self, function, measure='ambient', **kwds): sage: x, y = polygens(QQ, 'x, y') sage: P = Polyhedron(vertices=[[0,0], [1,1]]) - sage: P.integrate(x*y) # optional - latte_int + sage: P.integrate(x*y) 0 sage: ixy = P.integrate(x*y, measure='induced'); ixy # optional - latte_int 0.4714045207910317? @@ -825,21 +832,21 @@ def integrate(self, function, measure='ambient', **kwds): sage: R. = QQ[] sage: P = polytopes.simplex(2) - sage: V = AA(P.volume(measure='induced')) # optional - sage.rings.number_field - sage: V.radical_expression() # optional - sage.rings.number_field sage.symbolic + sage: V = AA(P.volume(measure='induced')) # needs sage.rings.number_field + sage: V.radical_expression() # needs sage.rings.number_field sage.symbolic 1/2*sqrt(3) - sage: P.integrate(R(1), measure='induced') == V # optional - latte_int sage.rings.number_field sage.symbolic + sage: P.integrate(R(1), measure='induced') == V # optional - latte_int, needs sage.rings.number_field sage.symbolic True Computing the mass center:: - sage: (P.integrate(x, measure='induced') # optional - latte_int sage.rings.number_field sage.symbolic + sage: (P.integrate(x, measure='induced') # optional - latte_int, needs sage.rings.number_field sage.symbolic ....: / V).radical_expression() 1/3 - sage: (P.integrate(y, measure='induced') # optional - latte_int sage.rings.number_field sage.symbolic + sage: (P.integrate(y, measure='induced') # optional - latte_int, needs sage.rings.number_field sage.symbolic ....: / V).radical_expression() 1/3 - sage: (P.integrate(z, measure='induced') # optional - latte_int sage.rings.number_field sage.symbolic + sage: (P.integrate(z, measure='induced') # optional - latte_int, needs sage.rings.number_field sage.symbolic ....: / V).radical_expression() 1/3 @@ -854,8 +861,8 @@ def integrate(self, function, measure='ambient', **kwds): Testing a polytope with non-rational vertices:: - sage: P = polytopes.icosahedron() # optional - sage.rings.number_field - sage: P.integrate(x^2*y^2*z^2) # optional - latte_int sage.rings.number_field + sage: P = polytopes.icosahedron() # needs sage.rings.number_field + sage: P.integrate(x^2*y^2*z^2) # optional - latte_int, needs sage.rings.number_field Traceback (most recent call last): ... TypeError: the base ring must be ZZ, QQ, or RDF @@ -870,7 +877,7 @@ def integrate(self, function, measure='ambient', **kwds): Testing a polytope with floating point coordinates:: sage: P = Polyhedron(vertices=[[0, 0], [1, 0], [1.1, 1.1], [0, 1]]) - sage: P.integrate('[[1,[2,2]]]') # optional - latte_int + sage: P.integrate('[[1,[2,2]]]') Traceback (most recent call last): ... TypeError: LattE integrale cannot be applied over inexact rings diff --git a/src/sage/geometry/polyhedron/base_QQ.py b/src/sage/geometry/polyhedron/base_QQ.py index 7aa1c568480..007f000eb56 100644 --- a/src/sage/geometry/polyhedron/base_QQ.py +++ b/src/sage/geometry/polyhedron/base_QQ.py @@ -132,7 +132,7 @@ def integral_points_count(self, verbose=False, use_Hrepresentation=False, sage: Q = P*(8/9) sage: Q.integral_points_count() 1 - sage: Q.integral_points_count(explicit_enumeration_threshold=0) # optional - latte_int + sage: Q.integral_points_count(explicit_enumeration_threshold=0) 1 Unbounded polyhedra (with or without lattice points) are not supported:: @@ -150,12 +150,12 @@ def integral_points_count(self, verbose=False, use_Hrepresentation=False, "Fibonacci" knapsacks (preprocessing helps a lot):: - sage: def fibonacci_knapsack(d, b, backend=None): # optional - sage.combinat + sage: def fibonacci_knapsack(d, b, backend=None): ....: lp = MixedIntegerLinearProgram(base_ring=QQ) ....: x = lp.new_variable(nonnegative=True) ....: lp.add_constraint(lp.sum(fibonacci(i+3)*x[i] for i in range(d)) <= b) ....: return lp.polyhedron(backend=backend) - sage: fibonacci_knapsack(20, 12).integral_points_count() # does not finish with preprocess=False # optional - sage.combinat + sage: fibonacci_knapsack(20, 12).integral_points_count() # does not finish with preprocess=False # needs sage.combinat 33 TESTS: @@ -163,10 +163,10 @@ def integral_points_count(self, verbose=False, use_Hrepresentation=False, We check that :trac:`21491` is fixed:: sage: P = Polyhedron(ieqs=[], eqns=[[-10,0,1],[-10,1,0]]) - sage: P.integral_points_count() # optional - latte_int + sage: P.integral_points_count() 1 sage: P = Polyhedron(ieqs=[], eqns=[[-11,0,2],[-10,1,0]]) - sage: P.integral_points_count() # optional - latte_int + sage: P.integral_points_count() 0 """ if self.is_empty(): @@ -296,23 +296,24 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, 7/2*t^3 + 2*t^2 - 1/2*t + 1 sage: poly(1) # optional - latte_int 6 - sage: len(simplex.integral_points()) # optional - latte_int + sage: len(simplex.integral_points()) 6 sage: poly(2) # optional - latte_int 36 - sage: len((2*simplex).integral_points()) # optional - latte_int + sage: len((2*simplex).integral_points()) 36 Now we find the same Ehrhart polynomial, this time using ``engine='normaliz'``. To use the Normaliz engine, the ``simplex`` must be defined with ``backend='normaliz'``:: - sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), # optional - pynormaliz + sage: # optional - pynormaliz + sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), ....: (-3,2,1), (1,-1,-2)], ....: backend='normaliz') - sage: simplex = simplex.change_ring(QQ) # optional - pynormaliz - sage: poly = simplex.ehrhart_polynomial(engine='normaliz') # optional - pynormaliz - sage: poly # optional - pynormaliz + sage: simplex = simplex.change_ring(QQ) + sage: poly = simplex.ehrhart_polynomial(engine='normaliz') + sage: poly 7/2*t^3 + 2*t^2 - 1/2*t + 1 If the ``engine='normaliz'``, the backend should be ``'normaliz'``, otherwise @@ -321,7 +322,7 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), ....: (-3,2,1), (1,-1,-2)]) sage: simplex = simplex.change_ring(QQ) - sage: simplex.ehrhart_polynomial(engine='normaliz') # optional - pynormaliz + sage: simplex.ehrhart_polynomial(engine='normaliz') Traceback (most recent call last): ... TypeError: The backend of the polyhedron should be 'normaliz' @@ -348,11 +349,12 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, The cache of the Ehrhart polynomial is being pickled:: - sage: P = polytopes.cube().change_ring(QQ) # optional - latte_int - sage: P.ehrhart_polynomial() # optional - latte_int + sage: # optional - latte_int + sage: P = polytopes.cube().change_ring(QQ) + sage: P.ehrhart_polynomial() 8*t^3 + 12*t^2 + 6*t + 1 - sage: Q = loads(dumps(P)) # optional - latte_int - sage: Q.ehrhart_polynomial.is_in_cache() # optional - latte_int + sage: Q = loads(dumps(P)) + sage: Q.ehrhart_polynomial.is_in_cache() True """ # check if ``self`` is compact and has vertices in ZZ @@ -525,32 +527,35 @@ def ehrhart_quasipolynomial(self, variable='t', engine=None, verbose=False, If the polytope happens to be a lattice polytope, the Ehrhart polynomial is returned:: - sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), # optional - pynormaliz + sage: # optional - pynormaliz + sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), ....: (-3,2,1), (1,-1,-2)], ....: backend='normaliz') - sage: simplex = simplex.change_ring(QQ) # optional - pynormaliz - sage: poly = simplex.ehrhart_quasipolynomial( # optional - pynormaliz + sage: simplex = simplex.change_ring(QQ) + sage: poly = simplex.ehrhart_quasipolynomial( ....: engine='normaliz'); poly 7/2*t^3 + 2*t^2 - 1/2*t + 1 - sage: simplex.ehrhart_polynomial() # optional - pynormaliz latte_int + sage: simplex.ehrhart_polynomial() # optional - latte_int 7/2*t^3 + 2*t^2 - 1/2*t + 1 TESTS: The cache of the Ehrhart quasipolynomial is being pickled:: - sage: P = polytopes.cuboctahedron(backend='normaliz')/2 # optional - pynormaliz - sage: P.ehrhart_quasipolynomial() # optional - pynormaliz + sage: # optional - pynormaliz + sage: P = polytopes.cuboctahedron(backend='normaliz')/2 + sage: P.ehrhart_quasipolynomial() (5/6*t^3 + 2*t^2 + 5/3*t + 1, 5/6*t^3 + 1/2*t^2 + 1/6*t - 1/2) - sage: Q = loads(dumps(P)) # optional - pynormaliz - sage: Q.ehrhart_quasipolynomial.is_in_cache() # optional - pynormaliz + sage: Q = loads(dumps(P)) + sage: Q.ehrhart_quasipolynomial.is_in_cache() True - sage: P = polytopes.cuboctahedron().change_ring(QQ) # optional - latte_int - sage: P.ehrhart_quasipolynomial(engine='latte') # optional - latte_int + sage: # optional - latte_int + sage: P = polytopes.cuboctahedron().change_ring(QQ) + sage: P.ehrhart_quasipolynomial(engine='latte') 20/3*t^3 + 8*t^2 + 10/3*t + 1 - sage: Q = loads(dumps(P)) # optional - latte_int - sage: Q.ehrhart_quasipolynomial.is_in_cache(engine='latte') # optional - latte_int + sage: Q = loads(dumps(P)) + sage: Q.ehrhart_quasipolynomial.is_in_cache(engine='latte') True """ if self.is_empty(): @@ -626,7 +631,7 @@ def _ehrhart_quasipolynomial_normaliz(self, variable='t'): TESTS:: sage: line_seg = Polyhedron(vertices=[[0],[1/2]]) - sage: line_seg._ehrhart_quasipolynomial_normaliz() # optional - pynormaliz + sage: line_seg._ehrhart_quasipolynomial_normaliz() Traceback (most recent call last): ... TypeError: The backend of the polyhedron should be 'normaliz' @@ -709,25 +714,26 @@ def _ehrhart_polynomial_latte(self, verbose=False, dual=None, 7/2*t^3 + 2*t^2 - 1/2*t + 1 sage: p(1) # optional - latte_int 6 - sage: len(P.integral_points()) # optional - latte_int + sage: len(P.integral_points()) 6 sage: p(2) # optional - latte_int 36 - sage: len((2*P).integral_points()) # optional - latte_int + sage: len((2*P).integral_points()) 36 The unit hypercubes:: + sage: # optional - latte_int sage: from itertools import product sage: def hypercube(d): ....: return Polyhedron(vertices=list(product([0,1], repeat=d))) - sage: hypercube(3)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(3)._ehrhart_polynomial_latte() t^3 + 3*t^2 + 3*t + 1 - sage: hypercube(4)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(4)._ehrhart_polynomial_latte() t^4 + 4*t^3 + 6*t^2 + 4*t + 1 - sage: hypercube(5)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(5)._ehrhart_polynomial_latte() t^5 + 5*t^4 + 10*t^3 + 10*t^2 + 5*t + 1 - sage: hypercube(6)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(6)._ehrhart_polynomial_latte() t^6 + 6*t^5 + 15*t^4 + 20*t^3 + 15*t^2 + 6*t + 1 TESTS: @@ -863,19 +869,20 @@ def fixed_subpolytope(self, vertex_permutation): The next example shows that :meth:`fixed_subpolytope` works for rational polytopes:: - sage: P = Polyhedron(vertices=[[0], [1/2]], # optional - pynormaliz + sage: # optional - pynormaliz + sage: P = Polyhedron(vertices=[[0], [1/2]], ....: backend='normaliz') - sage: P.vertices() # optional - pynormaliz + sage: P.vertices() (A vertex at (0), A vertex at (1/2)) - sage: G = P.restricted_automorphism_group( # optional - pynormaliz + sage: G = P.restricted_automorphism_group( ....: output='permutation'); G Permutation Group with generators [(0,1)] - sage: len(G) # optional - pynormaliz + sage: len(G) 2 - sage: fixed_set = P.fixed_subpolytope(G.gens()[0]) # optional - pynormaliz - sage: fixed_set # optional - pynormaliz + sage: fixed_set = P.fixed_subpolytope(G.gens()[0]) + sage: fixed_set A 0-dimensional polyhedron in QQ^1 defined as the convex hull of 1 vertex - sage: fixed_set.vertices_list() # optional - pynormaliz + sage: fixed_set.vertices_list() [[1/4]] """ if self.is_empty(): @@ -939,23 +946,24 @@ def fixed_subpolytopes(self, conj_class_reps): Here is an example for the square:: - sage: p = polytopes.hypercube(2, backend='normaliz'); p # optional - pynormaliz + sage: # optional - pynormaliz, needs sage.groups + sage: p = polytopes.hypercube(2, backend='normaliz'); p A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices - sage: aut_p = p.restricted_automorphism_group( # optional - pynormaliz sage.groups + sage: aut_p = p.restricted_automorphism_group( ....: output='permutation') - sage: aut_p.order() # optional - pynormaliz sage.groups + sage: aut_p.order() 8 - sage: conj_list = aut_p.conjugacy_classes_representatives() # optional - pynormaliz sage.groups - sage: fixedpolytopes_dict = p.fixed_subpolytopes(conj_list) # optional - pynormaliz sage.groups - sage: fixedpolytopes_dict[aut_p([(0,3),(1,2)])] # optional - pynormaliz sage.groups + sage: conj_list = aut_p.conjugacy_classes_representatives() + sage: fixedpolytopes_dict = p.fixed_subpolytopes(conj_list) + sage: fixedpolytopes_dict[aut_p([(0,3),(1,2)])] A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex TESTS:: sage: P = Polyhedron(vertices=[[1, 1]], rays=[[1, 1]]) - sage: aut_P = P.restricted_automorphism_group(output='permutation') # optional - sage.groups - sage: conj_list = aut_P.conjugacy_classes_representatives() # optional - sage.groups - sage: P.fixed_subpolytopes(conj_list) # optional - sage.groups + sage: aut_P = P.restricted_automorphism_group(output='permutation') # needs sage.groups + sage: conj_list = aut_P.conjugacy_classes_representatives() # needs sage.groups + sage: P.fixed_subpolytopes(conj_list) # needs sage.groups Traceback (most recent call last): ... NotImplementedError: unbounded polyhedra are not supported @@ -1021,15 +1029,16 @@ class functions. is equal to 1 = `\chi_{trivial}` (Prop 6.1 [Stap2011]_). Here is the computation for the 3-dimensional standard simplex:: - sage: S = polytopes.simplex(3, backend='normaliz'); S # optional - pynormaliz + sage: # optional - pynormaliz + sage: S = polytopes.simplex(3, backend='normaliz'); S A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 4 vertices - sage: G = S.restricted_automorphism_group( # optional - pynormaliz + sage: G = S.restricted_automorphism_group( ....: output='permutation') - sage: G.is_isomorphic(SymmetricGroup(4)) # optional - pynormaliz + sage: G.is_isomorphic(SymmetricGroup(4)) True - sage: Hstar = S._Hstar_function_normaliz(G); Hstar # optional - pynormaliz + sage: Hstar = S._Hstar_function_normaliz(G); Hstar chi_4 - sage: G.character_table() # optional - pynormaliz + sage: G.character_table() [ 1 -1 1 1 -1] [ 3 -1 0 -1 1] [ 2 0 -1 2 0] @@ -1041,26 +1050,27 @@ class functions. `\pm(0,0,1),\pm(1,0,1), \pm(0,1,1), \pm(1,1,1)` and let G = `\Zmod{2}` act on P as follows:: - sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], # optional - pynormaliz + sage: # optional - pynormaliz + sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], ....: [-1,0,-1], [0,1,1], ....: [0,-1,-1], [1,1,1], [-1,-1,-1]], ....: backend='normaliz') - sage: K = P.restricted_automorphism_group( # optional - pynormaliz + sage: K = P.restricted_automorphism_group( ....: output='permutation') - sage: G = K.subgroup(gens=[K([(0,2),(1,3),(4,6),(5,7)])]) # optional - pynormaliz - sage: conj_reps = G.conjugacy_classes_representatives() # optional - pynormaliz - sage: Dict = P.permutations_to_matrices(conj_reps, # optional - pynormaliz + sage: G = K.subgroup(gens=[K([(0,2),(1,3),(4,6),(5,7)])]) + sage: conj_reps = G.conjugacy_classes_representatives() + sage: Dict = P.permutations_to_matrices(conj_reps, ....: acting_group=G) - sage: list(Dict.keys())[0] # optional - pynormaliz + sage: list(Dict.keys())[0] (0,2)(1,3)(4,6)(5,7) - sage: list(Dict.values())[0] # optional - pynormaliz + sage: list(Dict.values())[0] [-1 0 1 0] [ 0 1 0 0] [ 0 0 1 0] [ 0 0 0 1] - sage: len(G) # optional - pynormaliz + sage: len(G) 2 - sage: G.character_table() # optional - pynormaliz + sage: G.character_table() [ 1 1] [ 1 -1] @@ -1170,35 +1180,37 @@ class functions of the acting group. A character `\rho` is effective if The `H^*` series of the two-dimensional permutahedron under the action of the symmetric group is effective:: - sage: p3 = polytopes.permutahedron(3, backend='normaliz') # optional - pynormaliz - sage: G = p3.restricted_automorphism_group( # optional - pynormaliz + sage: # optional - pynormaliz + sage: p3 = polytopes.permutahedron(3, backend='normaliz') + sage: G = p3.restricted_automorphism_group( ....: output='permutation') - sage: reflection12 = G([(0,2),(1,4),(3,5)]) # optional - pynormaliz - sage: reflection23 = G([(0,1),(2,3),(4,5)]) # optional - pynormaliz - sage: S3 = G.subgroup(gens=[reflection12, reflection23]) # optional - pynormaliz - sage: S3.is_isomorphic(SymmetricGroup(3)) # optional - pynormaliz + sage: reflection12 = G([(0,2),(1,4),(3,5)]) + sage: reflection23 = G([(0,1),(2,3),(4,5)]) + sage: S3 = G.subgroup(gens=[reflection12, reflection23]) + sage: S3.is_isomorphic(SymmetricGroup(3)) True - sage: Hstar = p3.Hstar_function(S3) # optional - pynormaliz - sage: Hlin = p3.Hstar_function(S3, # optional - pynormaliz + sage: Hstar = p3.Hstar_function(S3) + sage: Hlin = p3.Hstar_function(S3, ....: output='Hstar_as_lin_comb') - sage: p3.is_effective(Hstar, Hlin) # optional - pynormaliz + sage: p3.is_effective(Hstar, Hlin) True If the `H^*`-series is not polynomial, then it is not effective:: - sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], # optional - pynormaliz + sage: # optional - pynormaliz + sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], ....: [-1,0,-1], [0,1,1], ....: [0,-1,-1], [1,1,1], [-1,-1,-1]], ....: backend='normaliz') - sage: G = P.restricted_automorphism_group( # optional - pynormaliz + sage: G = P.restricted_automorphism_group( ....: output='permutation') - sage: H = G.subgroup(gens=[G([(0,2),(1,3),(4,6),(5,7)])]) # optional - pynormaliz - sage: Hstar = P.Hstar_function(H); Hstar # optional - pynormaliz + sage: H = G.subgroup(gens=[G([(0,2),(1,3),(4,6),(5,7)])]) + sage: Hstar = P.Hstar_function(H); Hstar (chi_0*t^4 + (3*chi_0 + 3*chi_1)*t^3 + (8*chi_0 + 2*chi_1)*t^2 + (3*chi_0 + 3*chi_1)*t + chi_0)/(t + 1) - sage: Hstar_lin = P.Hstar_function(H, # optional - pynormaliz + sage: Hstar_lin = P.Hstar_function(H, ....: output='Hstar_as_lin_comb') - sage: P.is_effective(Hstar, Hstar_lin) # optional - pynormaliz + sage: P.is_effective(Hstar, Hstar_lin) False """ if self.is_empty(): diff --git a/src/sage/geometry/polyhedron/base_ZZ.py b/src/sage/geometry/polyhedron/base_ZZ.py index b9b36bd6a48..7e360658341 100644 --- a/src/sage/geometry/polyhedron/base_ZZ.py +++ b/src/sage/geometry/polyhedron/base_ZZ.py @@ -79,7 +79,7 @@ def is_lattice_polytope(self): sage: polytopes.cross_polytope(3).is_lattice_polytope() True - sage: polytopes.regular_polygon(5).is_lattice_polytope() # optional - sage.rings.number_field + sage: polytopes.regular_polygon(5).is_lattice_polytope() # needs sage.rings.number_field False TESTS: @@ -163,25 +163,26 @@ def _ehrhart_polynomial_latte(self, verbose=False, dual=None, 7/2*t^3 + 2*t^2 - 1/2*t + 1 sage: p(1) # optional - latte_int 6 - sage: len(P.integral_points()) # optional - latte_int + sage: len(P.integral_points()) 6 sage: p(2) # optional - latte_int 36 - sage: len((2*P).integral_points()) # optional - latte_int + sage: len((2*P).integral_points()) 36 The unit hypercubes:: + sage: # optional - latte_int sage: from itertools import product sage: def hypercube(d): ....: return Polyhedron(vertices=list(product([0,1],repeat=d))) - sage: hypercube(3)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(3)._ehrhart_polynomial_latte() t^3 + 3*t^2 + 3*t + 1 - sage: hypercube(4)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(4)._ehrhart_polynomial_latte() t^4 + 4*t^3 + 6*t^2 + 4*t + 1 - sage: hypercube(5)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(5)._ehrhart_polynomial_latte() t^5 + 5*t^4 + 10*t^3 + 10*t^2 + 5*t + 1 - sage: hypercube(6)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(6)._ehrhart_polynomial_latte() t^6 + 6*t^5 + 15*t^4 + 20*t^3 + 15*t^2 + 6*t + 1 TESTS: @@ -281,7 +282,7 @@ def _ehrhart_polynomial_normaliz(self, variable='t'): Receive a type error if the backend is not normaliz:: sage: c = Polyhedron(vertices = [[0,0,0],[0,0,1],[0,1,0],[0,1,1],[1,0,0],[1,0,1],[1,1,0],[1,1,1]]) - sage: c._ehrhart_polynomial_normaliz() # optional - pynormaliz + sage: c._ehrhart_polynomial_normaliz() Traceback (most recent call last): ... TypeError: The polyhedron's backend should be 'normaliz' @@ -367,11 +368,11 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, dual=None 7/2*t^3 + 2*t^2 - 1/2*t + 1 sage: poly(1) # optional - latte_int 6 - sage: len(simplex.integral_points()) # optional - latte_int + sage: len(simplex.integral_points()) 6 sage: poly(2) # optional - latte_int 36 - sage: len((2*simplex).integral_points()) # optional - latte_int + sage: len((2*simplex).integral_points()) 36 Now we find the same Ehrhart polynomial, this time using @@ -387,7 +388,7 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, dual=None it returns an error:: sage: simplex = Polyhedron(vertices=[(0,0,0),(3,3,3),(-3,2,1),(1,-1,-2)]) - sage: simplex.ehrhart_polynomial(engine='normaliz') # optional - pynormaliz + sage: simplex.ehrhart_polynomial(engine='normaliz') Traceback (most recent call last): ... TypeError: The polyhedron's backend should be 'normaliz' @@ -399,27 +400,29 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, dual=None hypercube, and the coefficient of the leading monomial equals the volume of the unit hypercube:: + sage: # optional - latte_int sage: from itertools import product sage: def hypercube(d): ....: return Polyhedron(vertices=list(product([0,1],repeat=d))) - sage: hypercube(3).ehrhart_polynomial() # optional - latte_int + sage: hypercube(3).ehrhart_polynomial() t^3 + 3*t^2 + 3*t + 1 - sage: hypercube(4).ehrhart_polynomial() # optional - latte_int + sage: hypercube(4).ehrhart_polynomial() t^4 + 4*t^3 + 6*t^2 + 4*t + 1 - sage: hypercube(5).ehrhart_polynomial() # optional - latte_int + sage: hypercube(5).ehrhart_polynomial() t^5 + 5*t^4 + 10*t^3 + 10*t^2 + 5*t + 1 - sage: hypercube(6).ehrhart_polynomial() # optional - latte_int + sage: hypercube(6).ehrhart_polynomial() t^6 + 6*t^5 + 15*t^4 + 20*t^3 + 15*t^2 + 6*t + 1 + sage: # optional - pynormaliz sage: def hypercube(d): ....: return Polyhedron(vertices=list(product([0,1],repeat=d)),backend='normaliz') - sage: hypercube(3).ehrhart_polynomial(engine='normaliz') # optional - pynormaliz + sage: hypercube(3).ehrhart_polynomial(engine='normaliz') t^3 + 3*t^2 + 3*t + 1 - sage: hypercube(4).ehrhart_polynomial(engine='normaliz') # optional - pynormaliz + sage: hypercube(4).ehrhart_polynomial(engine='normaliz') t^4 + 4*t^3 + 6*t^2 + 4*t + 1 - sage: hypercube(5).ehrhart_polynomial(engine='normaliz') # optional - pynormaliz + sage: hypercube(5).ehrhart_polynomial(engine='normaliz') t^5 + 5*t^4 + 10*t^3 + 10*t^2 + 5*t + 1 - sage: hypercube(6).ehrhart_polynomial(engine='normaliz') # optional - pynormaliz + sage: hypercube(6).ehrhart_polynomial(engine='normaliz') t^6 + 6*t^5 + 15*t^4 + 20*t^3 + 15*t^2 + 6*t + 1 An empty polyhedron:: @@ -626,8 +629,8 @@ def fibration_generator(self, dim): EXAMPLES:: - sage: P = Polyhedron(toric_varieties.P4_11169().fan().rays(), base_ring=ZZ) # optional - palp - sage: list(P.fibration_generator(2)) # optional - palp + sage: P = Polyhedron(toric_varieties.P4_11169().fan().rays(), base_ring=ZZ) # needs palp sage.graphs + sage: list(P.fibration_generator(2)) # needs palp sage.graphs [A 2-dimensional polyhedron in ZZ^4 defined as the convex hull of 3 vertices] """ from sage.combinat.combination import Combinations diff --git a/src/sage/geometry/polyhedron/base_number_field.py b/src/sage/geometry/polyhedron/base_number_field.py index 40b9017dc53..9491fce4e75 100644 --- a/src/sage/geometry/polyhedron/base_number_field.py +++ b/src/sage/geometry/polyhedron/base_number_field.py @@ -32,12 +32,12 @@ def _number_field_elements_from_algebraics_list_of_lists_of_lists(listss, **kwds EXAMPLES:: - sage: rt2 = AA(sqrt(2)); rt2 # optional - sage.rings.number_field + sage: rt2 = AA(sqrt(2)); rt2 # needs sage.rings.number_field sage.symbolic 1.414213562373095? - sage: rt3 = AA(sqrt(3)); rt3 # optional - sage.rings.number_field + sage: rt3 = AA(sqrt(3)); rt3 # needs sage.rings.number_field sage.symbolic 1.732050807568878? sage: from sage.geometry.polyhedron.base_number_field import _number_field_elements_from_algebraics_list_of_lists_of_lists - sage: K, results, hom = _number_field_elements_from_algebraics_list_of_lists_of_lists([[[rt2], [1]], [[rt3]], [[1], []]]); results # optional - sage.rings.number_field + sage: K, results, hom = _number_field_elements_from_algebraics_list_of_lists_of_lists([[[rt2], [1]], [[rt3]], [[1], []]]); results # needs sage.rings.number_field sage.symbolic [[[-a^3 + 3*a], [1]], [[a^2 - 2]], [[1], []]] """ from sage.rings.qqbar import number_field_elements_from_algebraics @@ -58,28 +58,29 @@ def _compute_data_lists_and_internal_base_ring(self, data_lists, convert_QQ, con EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,1/2), (2,0), (4,5/6)], # optional - pynormaliz + sage: # optional - pynormaliz, needs sage.rings.number_field + sage: p = Polyhedron(vertices=[(0,1/2), (2,0), (4,5/6)], ....: base_ring=AA, backend='normaliz') - sage: def convert_QQ(ieqs, eqs): # optional - pynormaliz + sage: def convert_QQ(ieqs, eqs): ....: return [[1000*x for x in ieq] for ieq in ieqs], \ ....: [[1000*x for x in eq] for eq in eqs] - sage: def convert_NF(ieqs, eqs): # optional - pynormaliz + sage: def convert_NF(ieqs, eqs): ....: return ieqs, eqs - sage: p._compute_data_lists_and_internal_base_ring( # optional - pynormaliz + sage: p._compute_data_lists_and_internal_base_ring( ....: [[[1]], [[1/2]]], convert_QQ, convert_NF) (([[1000]], [[500]]), Rational Field) - sage: p._compute_data_lists_and_internal_base_ring( # optional - pynormaliz + sage: p._compute_data_lists_and_internal_base_ring( ....: [[[AA(1)]], [[1/2]]], convert_QQ, convert_NF) (([[1000]], [[500]]), Rational Field) - sage: p._compute_data_lists_and_internal_base_ring( # optional - pynormaliz sage.rings.number_field + sage: p._compute_data_lists_and_internal_base_ring( ....: [[[AA(sqrt(2))]], [[1/2]]], convert_QQ, convert_NF) ([[[a]], [[1/2]]], Number Field in a with defining polynomial y^2 - 2 with a = 1.414213562373095?) TESTS:: - sage: K. = QuadraticField(-5) # optional - sage.rings.number_field - sage: p = Polyhedron(base_ring=K, # indirect doctest # optional - pynormaliz sage.rings.number_field + sage: K. = QuadraticField(-5) # needs sage.rings.number_field + sage: p = Polyhedron(base_ring=K, # indirect doctest # optional - pynormaliz, needs sage.rings.number_field ....: backend='normaliz', ....: vertices=[(a,1/2), (2,0), (4,5/6)]) Traceback (most recent call last): @@ -88,11 +89,11 @@ def _compute_data_lists_and_internal_base_ring(self, data_lists, convert_QQ, con Checks that :trac:`30248` is fixed:: - sage: q = Polyhedron(base_ring=AA, # indirect doctest # optional - pynormaliz sage.rings.number_field + sage: q = Polyhedron(base_ring=AA, # indirect doctest # optional - pynormaliz, needs sage.rings.number_field ....: backend='normaliz', ....: rays=[(0, 0, 1), (0, 1, -1), (1, 0, -1)]); q A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays - sage: -q # optional - pynormaliz sage.rings.number_field + sage: -q # optional - pynormaliz, needs sage.rings.number_field A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays """ from sage.categories.number_fields import NumberFields diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index d25ca1ceebf..5a07abb2408 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -49,14 +49,14 @@ Obtaining edges and ridges:: Vertex-graph and facet-graph:: - sage: C.vertex_graph() # optional - sage.graphs + sage: C.vertex_graph() # needs sage.graphs Graph on 16 vertices - sage: C.facet_graph() # optional - sage.graphs + sage: C.facet_graph() # needs sage.graphs Graph on 8 vertices Face lattice:: - sage: C.face_lattice() # optional - sage.combinat + sage: C.face_lattice() # needs sage.combinat Finite lattice containing 82 elements Face iterator:: @@ -328,7 +328,7 @@ cdef class CombinatorialPolyhedron(SageObject): Traceback (most recent call last): ... ValueError: the combinatorial polyhedron was not initialized - sage: C.face_lattice() # optional - sage.combinat + sage: C.face_lattice() # needs sage.combinat Traceback (most recent call last): ... ValueError: the combinatorial polyhedron was not initialized @@ -640,16 +640,17 @@ cdef class CombinatorialPolyhedron(SageObject): TESTS:: - sage: P = polytopes.permutahedron(4) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C1 = loads(C.dumps()) # optional - sage.combinat - sage: it = C.face_generator() # optional - sage.combinat - sage: it1 = C1.face_generator() # optional - sage.combinat - sage: tup = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(4) + sage: C = CombinatorialPolyhedron(P) + sage: C1 = loads(C.dumps()) + sage: it = C.face_generator() + sage: it1 = C1.face_generator() + sage: tup = tuple((face.ambient_Vrepresentation(), ....: face.ambient_Hrepresentation()) for face in it) - sage: tup1 = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + sage: tup1 = tuple((face.ambient_Vrepresentation(), ....: face.ambient_Hrepresentation()) for face in it1) - sage: tup == tup1 # optional - sage.combinat + sage: tup == tup1 True sage: P = polytopes.cyclic_polytope(4,10) @@ -747,9 +748,9 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(3) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.Hrepresentation() # optional - sage.combinat + sage: P = polytopes.permutahedron(3) + sage: C = CombinatorialPolyhedron(P) + sage: C.Hrepresentation() (An inequality (1, 1, 0) x - 3 >= 0, An inequality (-1, -1, 0) x + 5 >= 0, An inequality (0, 1, 0) x - 1 >= 0, @@ -1104,10 +1105,11 @@ cdef class CombinatorialPolyhedron(SageObject): :: - sage: P = polytopes.permutahedron(5, backend='field') # optional - sage.combinat - sage: C = P.combinatorial_polyhedron() # optional - sage.combinat - sage: C.incidence_matrix.clear_cache() # optional - sage.combinat - sage: C.incidence_matrix() == P.incidence_matrix() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5, backend='field') + sage: C = P.combinatorial_polyhedron() + sage: C.incidence_matrix.clear_cache() + sage: C.incidence_matrix() == P.incidence_matrix() True The incidence matrix is consistent with @@ -1284,14 +1286,14 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.cyclic_polytope(3,5) sage: C = CombinatorialPolyhedron(P) - sage: G = C.vertex_graph(); G # optional - sage.graphs + sage: G = C.vertex_graph(); G # needs sage.graphs Graph on 5 vertices - sage: sorted(G.degree()) # optional - sage.graphs + sage: sorted(G.degree()) # needs sage.graphs [3, 3, 4, 4, 4] sage: P = Polyhedron(rays=[[1]]) sage: C = CombinatorialPolyhedron(P) - sage: C.graph() # optional - sage.graphs + sage: C.graph() # needs sage.graphs Graph on 1 vertex """ vertices = self.vertices(names=names) @@ -1392,11 +1394,12 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(2) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.ridges() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(2) + sage: C = CombinatorialPolyhedron(P) + sage: C.ridges() ((An inequality (1, 0) x - 1 >= 0, An inequality (-1, 0) x + 2 >= 0),) - sage: C.ridges(add_equations=True) # optional - sage.combinat + sage: C.ridges(add_equations=True) (((An inequality (1, 0) x - 1 >= 0, An equation (1, 1) x - 3 == 0), (An inequality (-1, 0) x + 2 >= 0, An equation (1, 1) x - 3 == 0)),) @@ -1565,25 +1568,25 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.cyclic_polytope(4,6) sage: C = CombinatorialPolyhedron(P) - sage: C.facet_graph() # optional - sage.graphs + sage: C.facet_graph() # needs sage.graphs Graph on 9 vertices TESTS:: sage: P = Polyhedron(ieqs=[[1,-1,0],[1,1,0]]) - sage: CombinatorialPolyhedron(P).facet_graph() # optional - sage.graphs + sage: CombinatorialPolyhedron(P).facet_graph() # needs sage.graphs Graph on 2 vertices Checking that :trac:`28604` is fixed:: sage: C = CombinatorialPolyhedron(polytopes.cube()); C A 3-dimensional combinatorial polyhedron with 6 facets - sage: C.facet_graph(names=False) # optional - sage.graphs + sage: C.facet_graph(names=False) # needs sage.graphs Graph on 6 vertices - sage: C = CombinatorialPolyhedron(polytopes.hypersimplex(5,2)); C # optional - sage.combinat + sage: C = CombinatorialPolyhedron(polytopes.hypersimplex(5,2)); C A 4-dimensional combinatorial polyhedron with 10 facets - sage: C.facet_graph() # optional - sage.graphs sage.combinat + sage: C.facet_graph() # needs sage.combinat sage.graphs Graph on 10 vertices """ face_iter = self.face_iter(self.dimension() - 1, algorithm='primal') @@ -1621,7 +1624,7 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.hypercube(2).pyramid() sage: C = CombinatorialPolyhedron(P) - sage: G = C.vertex_facet_graph(); G # optional - sage.graphs + sage: G = C.vertex_facet_graph(); G # needs sage.graphs Digraph on 10 vertices sage: C.Vrepresentation() (A vertex at (0, -1, -1), @@ -1629,7 +1632,7 @@ cdef class CombinatorialPolyhedron(SageObject): A vertex at (0, 1, -1), A vertex at (0, 1, 1), A vertex at (1, 0, 0)) - sage: sorted(G.neighbors_out(C.Vrepresentation()[4])) # optional - sage.graphs + sage: sorted(G.neighbors_out(C.Vrepresentation()[4])) # needs sage.graphs [An inequality (-1, -1, 0) x + 1 >= 0, An inequality (-1, 0, -1) x + 1 >= 0, An inequality (-1, 0, 1) x + 1 >= 0, @@ -1642,7 +1645,7 @@ cdef class CombinatorialPolyhedron(SageObject): with a string 'H' or 'V':: sage: C = CombinatorialPolyhedron(P.incidence_matrix()) - sage: C.vertex_facet_graph().vertices(sort=True) # optional - sage.graphs + sage: C.vertex_facet_graph().vertices(sort=True) # needs sage.graphs [('H', 0), ('H', 1), ('H', 2), @@ -1656,18 +1659,18 @@ cdef class CombinatorialPolyhedron(SageObject): If ``names`` is ``False`` then the vertices of the graph are given by integers:: - sage: C.vertex_facet_graph(names=False).vertices(sort=True) # optional - sage.graphs + sage: C.vertex_facet_graph(names=False).vertices(sort=True) # needs sage.graphs [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] TESTS: Test that :trac:`29898` is fixed:: - sage: Polyhedron().vertex_facet_graph() # optional - sage.graphs + sage: Polyhedron().vertex_facet_graph() # needs sage.graphs Digraph on 0 vertices - sage: Polyhedron([[0]]).vertex_facet_graph() # optional - sage.graphs + sage: Polyhedron([[0]]).vertex_facet_graph() # needs sage.graphs Digraph on 1 vertex - sage: Polyhedron([[0]]).vertex_facet_graph(False) # optional - sage.graphs + sage: Polyhedron([[0]]).vertex_facet_graph(False) # needs sage.graphs Digraph on 1 vertex """ from sage.graphs.digraph import DiGraph @@ -1736,9 +1739,9 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.f_vector() # optional - sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: C.f_vector() (1, 120, 240, 150, 30, 1) sage: P = polytopes.cyclic_polytope(6,10) @@ -1748,9 +1751,9 @@ cdef class CombinatorialPolyhedron(SageObject): Using two threads:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.f_vector(num_threads=2) # optional - sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: C.f_vector(num_threads=2) (1, 120, 240, 150, 30, 1) TESTS:: @@ -1808,7 +1811,7 @@ cdef class CombinatorialPolyhedron(SageObject): Obtain the entire flag-f-vector:: sage: C = polytopes.hypercube(4).combinatorial_polyhedron() - sage: C.flag_f_vector() # optional - sage.combinat + sage: C.flag_f_vector() # needs sage.combinat {(-1,): 1, (0,): 16, (0, 1): 64, @@ -1829,38 +1832,38 @@ cdef class CombinatorialPolyhedron(SageObject): Specify an entry:: - sage: C.flag_f_vector(0,3) # optional - sage.combinat + sage: C.flag_f_vector(0,3) # needs sage.combinat 64 - sage: C.flag_f_vector(2) # optional - sage.combinat + sage: C.flag_f_vector(2) # needs sage.combinat 24 Leading ``-1`` and trailing entry of dimension are allowed:: - sage: C.flag_f_vector(-1,0,3) # optional - sage.combinat + sage: C.flag_f_vector(-1,0,3) # needs sage.combinat 64 - sage: C.flag_f_vector(-1,0,3,4) # optional - sage.combinat + sage: C.flag_f_vector(-1,0,3,4) # needs sage.combinat 64 One can get the number of trivial faces:: - sage: C.flag_f_vector(-1) # optional - sage.combinat + sage: C.flag_f_vector(-1) # needs sage.combinat 1 - sage: C.flag_f_vector(4) # optional - sage.combinat + sage: C.flag_f_vector(4) # needs sage.combinat 1 Polyhedra with lines, have ``0`` entries accordingly:: sage: C = (Polyhedron(lines=[[1]]) * polytopes.hypercube(2)).combinatorial_polyhedron() - sage: C.flag_f_vector() # optional - sage.combinat + sage: C.flag_f_vector() # needs sage.combinat {(-1,): 1, (0, 1): 0, (0, 2): 0, (0,): 0, (1, 2): 8, (1,): 4, (2,): 4, 3: 1} If the arguments are not stricly increasing or out of range, a key error is raised:: - sage: C.flag_f_vector(-1,0,3,5) # optional - sage.combinat + sage: C.flag_f_vector(-1,0,3,5) # needs sage.combinat Traceback (most recent call last): ... KeyError: (0, 3, 5) - sage: C.flag_f_vector(-1,3,0) # optional - sage.combinat + sage: C.flag_f_vector(-1,3,0) # needs sage.combinat Traceback (most recent call last): ... KeyError: (3, 0) @@ -1888,7 +1891,7 @@ cdef class CombinatorialPolyhedron(SageObject): TESTS:: sage: C = CombinatorialPolyhedron(3) - sage: C._flag_f_vector() # optional - sage.combinat + sage: C._flag_f_vector() # needs sage.combinat {(-1,): 1, (0, 1): 0, (0, 2): 0, (0,): 0, (1, 2): 0, (1,): 0, (2,): 0, 3: 1} """ poly = self.face_lattice().flag_f_polynomial() @@ -2086,8 +2089,8 @@ cdef class CombinatorialPolyhedron(SageObject): sage: CombinatorialPolyhedron(cyclic).simpliciality() 3 - sage: hypersimplex = polytopes.hypersimplex(5,2) # optional - sage.combinat - sage: CombinatorialPolyhedron(hypersimplex).simpliciality() # optional - sage.combinat + sage: hypersimplex = polytopes.hypersimplex(5,2) + sage: CombinatorialPolyhedron(hypersimplex).simpliciality() 2 sage: cross = polytopes.cross_polytope(4) @@ -2194,16 +2197,16 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: hyper4 = polytopes.hypersimplex(4,2) # optional - sage.combinat - sage: CombinatorialPolyhedron(hyper4).simplicity() # optional - sage.combinat + sage: hyper4 = polytopes.hypersimplex(4,2) + sage: CombinatorialPolyhedron(hyper4).simplicity() 1 - sage: hyper5 = polytopes.hypersimplex(5,2) # optional - sage.combinat - sage: CombinatorialPolyhedron(hyper5).simplicity() # optional - sage.combinat + sage: hyper5 = polytopes.hypersimplex(5,2) + sage: CombinatorialPolyhedron(hyper5).simplicity() 2 - sage: hyper6 = polytopes.hypersimplex(6,2) # optional - sage.combinat - sage: CombinatorialPolyhedron(hyper6).simplicity() # optional - sage.combinat + sage: hyper6 = polytopes.hypersimplex(6,2) + sage: CombinatorialPolyhedron(hyper6).simplicity() 3 sage: P = polytopes.simplex(3) @@ -2631,15 +2634,16 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(4) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.join_of_Vrep(0,1) # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(4) + sage: C = CombinatorialPolyhedron(P) + sage: C.join_of_Vrep(0,1) A 1-dimensional face of a 3-dimensional combinatorial polyhedron - sage: C.join_of_Vrep(0,11).ambient_V_indices() # optional - sage.combinat + sage: C.join_of_Vrep(0,11).ambient_V_indices() (0, 1, 10, 11, 12, 13) - sage: C.join_of_Vrep(8).ambient_V_indices() # optional - sage.combinat + sage: C.join_of_Vrep(8).ambient_V_indices() (8,) - sage: C.join_of_Vrep().ambient_V_indices() # optional - sage.combinat + sage: C.join_of_Vrep().ambient_V_indices() () """ return self.face_generator().join_of_Vrep(*indices) @@ -2654,19 +2658,20 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: C = CombinatorialPolyhedron(P) # optional - sage.rings.number_field - sage: C.meet_of_Hrep(0) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron() + sage: C = CombinatorialPolyhedron(P) + sage: C.meet_of_Hrep(0) A 2-dimensional face of a 3-dimensional combinatorial polyhedron - sage: C.meet_of_Hrep(0).ambient_H_indices() # optional - sage.rings.number_field + sage: C.meet_of_Hrep(0).ambient_H_indices() (0,) - sage: C.meet_of_Hrep(0,1).ambient_H_indices() # optional - sage.rings.number_field + sage: C.meet_of_Hrep(0,1).ambient_H_indices() (0, 1) - sage: C.meet_of_Hrep(0,2).ambient_H_indices() # optional - sage.rings.number_field + sage: C.meet_of_Hrep(0,2).ambient_H_indices() (0, 2) - sage: C.meet_of_Hrep(0,2,3).ambient_H_indices() # optional - sage.rings.number_field + sage: C.meet_of_Hrep(0,2,3).ambient_H_indices() (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) - sage: C.meet_of_Hrep().ambient_H_indices() # optional - sage.rings.number_field + sage: C.meet_of_Hrep().ambient_H_indices() () """ return self.face_generator().meet_of_Hrep(*indices) @@ -2697,38 +2702,39 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(dimension=2) # optional - sage.combinat - sage: face = next(it); face # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(dimension=2) + sage: face = next(it); face A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_Vrepresentation() # optional - sage.combinat + sage: face.ambient_Vrepresentation() (A vertex at (1, 3, 2, 5, 4), A vertex at (2, 3, 1, 5, 4), A vertex at (3, 1, 2, 5, 4), A vertex at (3, 2, 1, 5, 4), A vertex at (2, 1, 3, 5, 4), A vertex at (1, 2, 3, 5, 4)) - sage: face = next(it); face # optional - sage.combinat + sage: face = next(it); face A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_Vrepresentation() # optional - sage.combinat + sage: face.ambient_Vrepresentation() (A vertex at (2, 1, 4, 5, 3), A vertex at (3, 2, 4, 5, 1), A vertex at (3, 1, 4, 5, 2), A vertex at (1, 3, 4, 5, 2), A vertex at (1, 2, 4, 5, 3), A vertex at (2, 3, 4, 5, 1)) - sage: face.ambient_Hrepresentation() # optional - sage.combinat + sage: face.ambient_Hrepresentation() (An inequality (0, 0, -1, -1, 0) x + 9 >= 0, An inequality (0, 0, 0, -1, 0) x + 5 >= 0, An equation (1, 1, 1, 1, 1) x - 15 == 0) - sage: face.ambient_H_indices() # optional - sage.combinat + sage: face.ambient_H_indices() (25, 29, 30) - sage: face = next(it); face # optional - sage.combinat + sage: face = next(it); face A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_H_indices() # optional - sage.combinat + sage: face.ambient_H_indices() (24, 29, 30) - sage: face.ambient_V_indices() # optional - sage.combinat + sage: face.ambient_V_indices() (32, 89, 90, 94) sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3],[0,2,3],[1,2,3]]) @@ -2840,31 +2846,31 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = Polyhedron(rays=[[1,0],[0,1]]) sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice() # optional - sage.combinat + sage: C.face_lattice() # needs sage.combinat Finite lattice containing 5 elements sage: P = Polyhedron(rays=[[1,0,0], [-1,0,0], [0,-1,0], [0,1,0]]) sage: C = CombinatorialPolyhedron(P) sage: P1 = Polyhedron(rays=[[1,0], [-1,0]]) sage: C1 = CombinatorialPolyhedron(P1) - sage: C.face_lattice().is_isomorphic(C1.face_lattice()) # optional - sage.combinat + sage: C.face_lattice().is_isomorphic(C1.face_lattice()) # needs sage.combinat True - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.face_lattice() # optional - sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: C.face_lattice() # needs sage.combinat Finite lattice containing 542 elements TESTS:: sage: P = polytopes.cyclic_polytope(4,10) sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice().is_isomorphic(P.face_lattice()) # optional - sage.combinat + sage: C.face_lattice().is_isomorphic(P.face_lattice()) # needs sage.combinat True - sage: P = polytopes.permutahedron(4) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.face_lattice().is_isomorphic(P.face_lattice()) # optional - sage.combinat + sage: P = polytopes.permutahedron(4) + sage: C = CombinatorialPolyhedron(P) + sage: C.face_lattice().is_isomorphic(P.face_lattice()) # needs sage.combinat True """ from sage.combinat.posets.lattices import FiniteLatticePoset @@ -2894,20 +2900,21 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.regular_polygon(4).pyramid() # optional - sage.rings.number_field - sage: C = CombinatorialPolyhedron(P) # optional - sage.rings.number_field - sage: D = C.hasse_diagram(); D # optional - sage.graphs sage.rings.number_field + sage: # needs sage.graphs sage.rings.number_field + sage: P = polytopes.regular_polygon(4).pyramid() + sage: C = CombinatorialPolyhedron(P) + sage: D = C.hasse_diagram(); D Digraph on 20 vertices - sage: D.average_degree() # optional - sage.graphs sage.rings.number_field + sage: D.average_degree() 21/5 - sage: D.relabel(C.face_by_face_lattice_index) # optional - sage.graphs sage.rings.number_field - sage: dim_0_vert = D.vertices(sort=True)[1:6]; dim_0_vert # optional - sage.graphs sage.rings.number_field + sage: D.relabel(C.face_by_face_lattice_index) + sage: dim_0_vert = D.vertices(sort=True)[1:6]; dim_0_vert [A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 0-dimensional face of a 3-dimensional combinatorial polyhedron] - sage: sorted(D.out_degree(vertices=dim_0_vert)) # optional - sage.graphs sage.rings.number_field + sage: sorted(D.out_degree(vertices=dim_0_vert)) [3, 3, 3, 3, 4] """ if not self._face_lattice_incidences: @@ -2936,12 +2943,12 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.cube() sage: C = CombinatorialPolyhedron(P) - sage: F = C.face_lattice() # optional - sage.combinat + sage: F = C.face_lattice() # needs sage.combinat sage: def f(i): ....: return (i, C._face_lattice_dimension(i)) ....: - sage: G = F.relabel(f) # optional - sage.combinat - sage: set(G._elements) # optional - sage.combinat + sage: G = F.relabel(f) # needs sage.combinat + sage: set(G._elements) # needs sage.combinat {(0, -1), (1, 0), (2, 0), @@ -2990,15 +2997,16 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: + sage: # needs sage.combinat sage: P = polytopes.cube() sage: C = CombinatorialPolyhedron(P) - sage: F = C.face_lattice() # optional - sage.combinat - sage: F # optional - sage.combinat + sage: F = C.face_lattice() + sage: F Finite lattice containing 28 elements - sage: G = F.relabel(C.face_by_face_lattice_index) # optional - sage.combinat - sage: G.level_sets()[0] # optional - sage.combinat + sage: G = F.relabel(C.face_by_face_lattice_index) + sage: G.level_sets()[0] [A -1-dimensional face of a 3-dimensional combinatorial polyhedron] - sage: G.level_sets()[3] # optional - sage.combinat + sage: G.level_sets()[3] [A 2-dimensional face of a 3-dimensional combinatorial polyhedron, A 2-dimensional face of a 3-dimensional combinatorial polyhedron, A 2-dimensional face of a 3-dimensional combinatorial polyhedron, @@ -3008,9 +3016,9 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = Polyhedron(rays=[[0,1], [1,0]]) sage: C = CombinatorialPolyhedron(P) - sage: F = C.face_lattice() # optional - sage.combinat - sage: G = F.relabel(C.face_by_face_lattice_index) # optional - sage.combinat - sage: G._elements # optional - sage.combinat + sage: F = C.face_lattice() # needs sage.combinat + sage: G = F.relabel(C.face_by_face_lattice_index) # needs sage.combinat + sage: G._elements # needs sage.combinat (A -1-dimensional face of a 2-dimensional combinatorial polyhedron, A 0-dimensional face of a 2-dimensional combinatorial polyhedron, A 1-dimensional face of a 2-dimensional combinatorial polyhedron, @@ -3018,8 +3026,8 @@ cdef class CombinatorialPolyhedron(SageObject): A 2-dimensional face of a 2-dimensional combinatorial polyhedron) sage: def f(i): return C.face_by_face_lattice_index(i).ambient_V_indices() - sage: G = F.relabel(f) # optional - sage.combinat - sage: G._elements # optional - sage.combinat + sage: G = F.relabel(f) # needs sage.combinat + sage: G._elements # needs sage.combinat ((), (0,), (0, 1), (0, 2), (0, 1, 2)) """ self._record_all_faces() # Initialize ``_all_faces``, if not done yet. @@ -3064,13 +3072,14 @@ cdef class CombinatorialPolyhedron(SageObject): sage: [face.ambient_V_indices() for face in chain] [(15,), (6, 15), (5, 6, 14, 15), (0, 5, 6, 7, 8, 9, 14, 15)] - sage: P = polytopes.permutahedron(4) # optional - sage.combinat - sage: C = P.combinatorial_polyhedron() # optional - sage.combinat - sage: chain = C.a_maximal_chain(); chain # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(4) + sage: C = P.combinatorial_polyhedron() + sage: chain = C.a_maximal_chain(); chain [A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 1-dimensional face of a 3-dimensional combinatorial polyhedron, A 2-dimensional face of a 3-dimensional combinatorial polyhedron] - sage: [face.ambient_V_indices() for face in chain] # optional - sage.combinat + sage: [face.ambient_V_indices() for face in chain] [(16,), (15, 16), (8, 9, 14, 15, 16, 17)] sage: P = Polyhedron(rays=[[1,0]], lines=[[0,1]]) @@ -3366,7 +3375,7 @@ cdef class CombinatorialPolyhedron(SageObject): sage: D.f_vector() (1, 6, 12, 8, 1) sage: D1 = P.polar().combinatorial_polyhedron() - sage: D1.face_lattice().is_isomorphic(D.face_lattice()) # optional - sage.combinat + sage: D1.face_lattice().is_isomorphic(D.face_lattice()) # needs sage.combinat True Polar is an alias to be consistent with :class:`~sage.geometry.polyhedron.base.Polyhedron_base`:: @@ -3416,7 +3425,7 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C1 = C.pyramid() sage: P1 = P.pyramid() sage: C2 = P1.combinatorial_polyhedron() - sage: C2.vertex_facet_graph().is_isomorphic(C1.vertex_facet_graph()) # optional - sage.combinat + sage: C2.vertex_facet_graph().is_isomorphic(C1.vertex_facet_graph()) # needs sage.combinat True One can specify a name for the new vertex:: @@ -3435,10 +3444,11 @@ cdef class CombinatorialPolyhedron(SageObject): One can specify a name for the new facets:: - sage: P = polytopes.regular_polygon(4) # optional - sage.rings.number_field - sage: C = P.combinatorial_polyhedron() # optional - sage.rings.number_field - sage: C1 = C.pyramid(new_facet='base') # optional - sage.rings.number_field - sage: C1.Hrepresentation() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.regular_polygon(4) + sage: C = P.combinatorial_polyhedron() + sage: C1 = C.pyramid(new_facet='base') + sage: C1.Hrepresentation() (An inequality (-1/2, 1/2) x + 1/2 >= 0, An inequality (-1/2, -1/2) x + 1/2 >= 0, An inequality (1/2, 0.50000000000000000?) x + 1/2 >= 0, @@ -3823,17 +3833,18 @@ cdef class CombinatorialPolyhedron(SageObject): TESTS:: - sage: P = polytopes.permutahedron(4) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator() # optional - sage.combinat - sage: tup = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(4) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator() + sage: tup = tuple((face.ambient_Vrepresentation(), ....: face.ambient_Hrepresentation()) for face in it) - sage: rg = range(1,sum(C.f_vector()) - 1) # optional - sage.combinat - sage: tup2 = tuple( # optional - sage.combinat + sage: rg = range(1,sum(C.f_vector()) - 1) + sage: tup2 = tuple( ....: (C.face_by_face_lattice_index(i).ambient_Vrepresentation(), ....: C.face_by_face_lattice_index(i).ambient_Hrepresentation()) ....: for i in rg) - sage: sorted(tup) == sorted(tup2) # optional - sage.combinat + sage: sorted(tup) == sorted(tup2) True sage: P = polytopes.cyclic_polytope(4,10) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx index e499afcbc1c..bf01025707f 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx @@ -22,9 +22,9 @@ Obtain a face from a face lattice index:: sage: P = polytopes.simplex(2) sage: C = CombinatorialPolyhedron(P) - sage: sorted(C.face_lattice()._elements) # optional - sage.combinat + sage: sorted(C.face_lattice()._elements) # needs sage.combinat [0, 1, 2, 3, 4, 5, 6, 7] - sage: face = C.face_by_face_lattice_index(0); face # optional - sage.combinat + sage: face = C.face_by_face_lattice_index(0); face A -1-dimensional face of a 2-dimensional combinatorial polyhedron Obtain further information regarding a face:: @@ -97,10 +97,10 @@ cdef class CombinatorialFace(SageObject): Obtain a combinatorial face from an index of the face lattice:: - sage: F = C.face_lattice() # optional - sage.combinat - sage: F._elements[3] # optional - sage.combinat + sage: F = C.face_lattice() # needs sage.combinat + sage: F._elements[3] # needs sage.combinat 34 - sage: C.face_by_face_lattice_index(29) # optional - sage.combinat + sage: C.face_by_face_lattice_index(29) A 1-dimensional face of a 5-dimensional combinatorial polyhedron Obtain the dimension of a combinatorial face:: @@ -260,15 +260,16 @@ cdef class CombinatorialFace(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(6) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(dimension=3, algorithm='primal') # optional - sage.combinat - sage: face = next(it) # optional - sage.combinat - sage: face.__repr__() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(6) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(dimension=3, algorithm='primal') + sage: face = next(it) + sage: face.__repr__() 'A 3-dimensional face of a 5-dimensional combinatorial polyhedron' - sage: it = C.face_generator(dimension=3, algorithm='dual') # optional - sage.combinat - sage: face = next(it) # optional - sage.combinat - sage: face.__repr__() # optional - sage.combinat + sage: it = C.face_generator(dimension=3, algorithm='dual') + sage: face = next(it) + sage: face.__repr__() 'A 3-dimensional face of a 5-dimensional combinatorial polyhedron' """ return "A {}-dimensional face of a {}-dimensional combinatorial polyhedron"\ @@ -318,15 +319,16 @@ cdef class CombinatorialFace(SageObject): TESTS:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: F = C.face_lattice() # optional - sage.combinat - sage: G = F.relabel(C.face_by_face_lattice_index) # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: F = C.face_lattice() + sage: G = F.relabel(C.face_by_face_lattice_index) sage: P = polytopes.cyclic_polytope(4,10) sage: C = CombinatorialPolyhedron(P) - sage: F = C.face_lattice() # optional - sage.combinat - sage: G = F.relabel(C.face_by_face_lattice_index) # optional - sage.combinat + sage: F = C.face_lattice() # needs sage.combinat + sage: G = F.relabel(C.face_by_face_lattice_index) # needs sage.combinat """ return self._hash_index @@ -349,7 +351,7 @@ cdef class CombinatorialFace(SageObject): sage: F2 = C.face_by_face_lattice_index(1) sage: F1 < F2 True - sage: for i,j in Combinations(range(28), 2): # optional - sage.combinat + sage: for i,j in Combinations(range(28), 2): ....: F1 = C.face_by_face_lattice_index(i) ....: F2 = C.face_by_face_lattice_index(j) ....: if F1.dim() != F2.dim(): @@ -361,7 +363,7 @@ cdef class CombinatorialFace(SageObject): sage: F2 = C.face_by_face_lattice_index(1) sage: F1 < F2 True - sage: for i,j in Combinations(range(28), 2): # optional - sage.combinat + sage: for i,j in Combinations(range(28), 2): ....: F1 = C.face_by_face_lattice_index(i) ....: F2 = C.face_by_face_lattice_index(j) ....: if F1.dim() != F2.dim(): @@ -501,16 +503,17 @@ cdef class CombinatorialFace(SageObject): EXAMPLES:: - sage: P = polytopes.associahedron(['A', 3]) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator() # optional - sage.combinat - sage: face = next(it) # optional - sage.combinat - sage: face.dimension() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.associahedron(['A', 3]) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator() + sage: face = next(it) + sage: face.dimension() 2 ``dim`` is an alias:: - sage: face.dim() # optional - sage.combinat + sage: face.dim() # needs sage.combinat 2 """ if self._dual: @@ -545,19 +548,20 @@ cdef class CombinatorialFace(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(dimension=2) # optional - sage.combinat - sage: face = next(it) # optional - sage.combinat - sage: face.ambient_Vrepresentation() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(dimension=2) + sage: face = next(it) + sage: face.ambient_Vrepresentation() (A vertex at (1, 3, 2, 5, 4), A vertex at (2, 3, 1, 5, 4), A vertex at (3, 1, 2, 5, 4), A vertex at (3, 2, 1, 5, 4), A vertex at (2, 1, 3, 5, 4), A vertex at (1, 2, 3, 5, 4)) - sage: face = next(it) # optional - sage.combinat - sage: face.ambient_Vrepresentation() # optional - sage.combinat + sage: face = next(it) + sage: face.ambient_Vrepresentation() (A vertex at (2, 1, 4, 5, 3), A vertex at (3, 2, 4, 5, 1), A vertex at (3, 1, 4, 5, 2), @@ -609,13 +613,14 @@ cdef class CombinatorialFace(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(dimension=2) # optional - sage.combinat - sage: face = next(it) # optional - sage.combinat - sage: next(it).ambient_V_indices() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(dimension=2) + sage: face = next(it) + sage: next(it).ambient_V_indices() (32, 91, 92, 93, 94, 95) - sage: next(it).ambient_V_indices() # optional - sage.combinat + sage: next(it).ambient_V_indices() (32, 89, 90, 94) sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3],[0,2,3],[1,2,3]]) @@ -688,14 +693,15 @@ cdef class CombinatorialFace(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(2) # optional - sage.combinat - sage: next(it).ambient_Hrepresentation() # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(2) + sage: next(it).ambient_Hrepresentation() (An inequality (1, 1, 1, 0, 0) x - 6 >= 0, An inequality (0, 0, 0, -1, 0) x + 5 >= 0, An equation (1, 1, 1, 1, 1) x - 15 == 0) - sage: next(it).ambient_Hrepresentation() # optional - sage.combinat + sage: next(it).ambient_Hrepresentation() (An inequality (0, 0, -1, -1, 0) x + 9 >= 0, An inequality (0, 0, 0, -1, 0) x + 5 >= 0, An equation (1, 1, 1, 1, 1) x - 15 == 0) @@ -748,21 +754,22 @@ cdef class CombinatorialFace(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(2) # optional - sage.combinat - sage: face = next(it) # optional - sage.combinat - sage: face.ambient_H_indices(add_equations=False) # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(2) + sage: face = next(it) + sage: face.ambient_H_indices(add_equations=False) (28, 29) - sage: face2 = next(it) # optional - sage.combinat - sage: face2.ambient_H_indices(add_equations=False) # optional - sage.combinat + sage: face2 = next(it) + sage: face2.ambient_H_indices(add_equations=False) (25, 29) Add the indices of the equation:: - sage: face.ambient_H_indices(add_equations=True) # optional - sage.combinat + sage: face.ambient_H_indices(add_equations=True) # needs sage.combinat (28, 29, 30) - sage: face2.ambient_H_indices(add_equations=True) # optional - sage.combinat + sage: face2.ambient_H_indices(add_equations=True) # needs sage.combinat (25, 29, 30) Another example:: @@ -828,13 +835,14 @@ cdef class CombinatorialFace(SageObject): Specifying whether to count the equations or not:: - sage: P = polytopes.permutahedron(5) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator(2) # optional - sage.combinat - sage: f = next(it) # optional - sage.combinat - sage: f.n_ambient_Hrepresentation(add_equations=True) # optional - sage.combinat + sage: # needs sage.combinat + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator(2) + sage: f = next(it) + sage: f.n_ambient_Hrepresentation(add_equations=True) 3 - sage: f.n_ambient_Hrepresentation(add_equations=False) # optional - sage.combinat + sage: f.n_ambient_Hrepresentation(add_equations=False) 2 TESTS:: @@ -877,7 +885,7 @@ cdef class CombinatorialFace(SageObject): sage: F.f_vector() (1, 5, 10, 10, 5, 1) sage: F_alt = polytopes.cyclic_polytope(4,5).combinatorial_polyhedron() - sage: F_alt.vertex_facet_graph().is_isomorphic(F.vertex_facet_graph()) # optional - sage.graphs + sage: F_alt.vertex_facet_graph().is_isomorphic(F.vertex_facet_graph()) # needs sage.graphs True Obtaining the quotient:: diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx index b670ad2e53f..baeb8fc4855 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx @@ -31,11 +31,12 @@ Obtain the facets of a polyhedron as :class:`~sage.geometry.polyhedron.combinato Obtain the Vrepresentation of a polyhedron as facet-incidences stored in :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces`:: + sage: # needs sage.combinat sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ ....: import incidence_matrix_to_bit_rep_of_Vrep - sage: P = polytopes.associahedron(['A',4]) # optional - sage.combinat - sage: face_list = incidence_matrix_to_bit_rep_of_Vrep(P.incidence_matrix()) # optional - sage.combinat - sage: face_list.compute_dimension() # optional - sage.combinat + sage: P = polytopes.associahedron(['A',4]) + sage: face_list = incidence_matrix_to_bit_rep_of_Vrep(P.incidence_matrix()) + sage: face_list.compute_dimension() 4 Obtain the facets of a polyhedron as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces` from a facet list:: diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx index cd24dd5be66..f0ac1e774a7 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx @@ -207,13 +207,13 @@ cdef class FaceIterator_base(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(4) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: it = C.face_generator() # indirect doctest # optional - sage.combinat + sage: P = polytopes.permutahedron(4) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_generator() # indirect doctest sage: f_vector = [1, 0, 0, 0, 1] - sage: for face in it: f_vector[face.dimension()+1] += 1 # optional - sage.combinat - sage: print ('f_vector of permutahedron(4): ', f_vector) # optional - sage.combinat + sage: for face in it: f_vector[face.dimension()+1] += 1 + sage: print ('f_vector of permutahedron(4): ', f_vector) f_vector of permutahedron(4): [1, 24, 36, 14, 1] sage: TestSuite(sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator).run() @@ -637,17 +637,18 @@ cdef class FaceIterator_base(SageObject): If the iterator has already been used, it must be reset before:: - sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: it = P.face_generator() # optional - sage.rings.number_field - sage: _ = next(it), next(it) # optional - sage.rings.number_field - sage: next(it).ambient_V_indices() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron() + sage: it = P.face_generator() + sage: _ = next(it), next(it) + sage: next(it).ambient_V_indices() (15, 16, 17, 18, 19) - sage: it.meet_of_Hrep(9,11) # optional - sage.rings.number_field + sage: it.meet_of_Hrep(9,11) Traceback (most recent call last): ... ValueError: please reset the face iterator - sage: it.reset() # optional - sage.rings.number_field - sage: it.meet_of_Hrep(9,11).ambient_H_indices() # optional - sage.rings.number_field + sage: it.reset() + sage: it.meet_of_Hrep(9,11).ambient_H_indices() (9, 11) TESTS: @@ -722,17 +723,18 @@ cdef class FaceIterator_base(SageObject): If the iterator has already been used, it must be reset before:: - sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: it = P.face_generator() # optional - sage.rings.number_field - sage: _ = next(it), next(it) # optional - sage.rings.number_field - sage: next(it).ambient_V_indices() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron() + sage: it = P.face_generator() + sage: _ = next(it), next(it) + sage: next(it).ambient_V_indices() (15, 16, 17, 18, 19) - sage: it.join_of_Vrep(1,10) # optional - sage.rings.number_field + sage: it.join_of_Vrep(1,10) Traceback (most recent call last): ... ValueError: please reset the face iterator - sage: it.reset() # optional - sage.rings.number_field - sage: it.join_of_Vrep(1,10).ambient_V_indices() # optional - sage.rings.number_field + sage: it.reset() + sage: it.join_of_Vrep(1,10).ambient_V_indices() (1, 10) In the case of an unbounded polyhedron, we try to make sense of the input:: @@ -846,9 +848,10 @@ cdef class FaceIterator_base(SageObject): The face iterator must not have the output dimension specified:: - sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: it = P.face_generator(2) # optional - sage.rings.number_field - sage: it._meet_of_coatoms(1,2) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron() + sage: it = P.face_generator(2) + sage: it._meet_of_coatoms(1,2) Traceback (most recent call last): ... ValueError: face iterator must not have the output dimension specified @@ -955,24 +958,26 @@ cdef class FaceIterator_base(SageObject): If the iterator has already been used, it must be reset before:: - sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: it = P.face_generator() # optional - sage.rings.number_field - sage: _ = next(it), next(it) # optional - sage.rings.number_field - sage: next(it).ambient_V_indices() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron() + sage: it = P.face_generator() + sage: _ = next(it), next(it) + sage: next(it).ambient_V_indices() (15, 16, 17, 18, 19) - sage: it._join_of_atoms(1,10) # optional - sage.rings.number_field + sage: it._join_of_atoms(1,10) Traceback (most recent call last): ... ValueError: please reset the face iterator - sage: it.reset() # optional - sage.rings.number_field - sage: it._join_of_atoms(1,10).ambient_V_indices() # optional - sage.rings.number_field + sage: it.reset() + sage: it._join_of_atoms(1,10).ambient_V_indices() (1, 10) The face iterator must not have the output dimension specified:: - sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: it = P.face_generator(2) # optional - sage.rings.number_field - sage: it._join_of_atoms(1,2) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = polytopes.dodecahedron() + sage: it = P.face_generator(2) + sage: it._join_of_atoms(1,2) Traceback (most recent call last): ... ValueError: face iterator must not have the output dimension specified @@ -1574,12 +1579,12 @@ cdef class FaceIterator(FaceIterator_base): r""" EXAMPLES:: - sage: P = polytopes.associahedron(['A',3]) # optional - sage.combinat - sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat - sage: C.face_generator() # optional - sage.combinat + sage: P = polytopes.associahedron(['A',3]) # needs sage.combinat + sage: C = CombinatorialPolyhedron(P) # needs sage.combinat + sage: C.face_generator() # needs sage.combinat Iterator over the proper faces of a 3-dimensional combinatorial polyhedron - sage: C.face_generator(1) # optional - sage.combinat + sage: C.face_generator(1) # needs sage.combinat Iterator over the 1-faces of a 3-dimensional combinatorial polyhedron """ if self.structure.output_dimension != -2: @@ -1845,11 +1850,11 @@ cdef class FaceIterator_geom(FaceIterator_base): r""" EXAMPLES:: - sage: P = polytopes.associahedron(['A',3]) # optional - sage.combinat - sage: P.face_generator() # optional - sage.combinat + sage: P = polytopes.associahedron(['A',3]) # needs sage.combinat + sage: P.face_generator() # needs sage.combinat Iterator over the faces of a 3-dimensional polyhedron in QQ^3 - sage: P.face_generator(1) # optional - sage.combinat + sage: P.face_generator(1) # needs sage.combinat Iterator over the 1-faces of a 3-dimensional polyhedron in QQ^3 """ if self._requested_dim is not None: diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx index d365ee3a24e..dffa76036fa 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx @@ -39,11 +39,12 @@ Obtain the facets of a polyhedron:: Obtain the Vrepresentation of a polyhedron as facet-incidences:: + sage: # needs sage.combinat sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ ....: import incidence_matrix_to_bit_rep_of_Vrep - sage: P = polytopes.associahedron(['A',3]) # optional - sage.combinat - sage: face_list = incidence_matrix_to_bit_rep_of_Vrep(P.incidence_matrix()) # optional - sage.combinat - sage: face_list.compute_dimension() # optional - sage.combinat + sage: P = polytopes.associahedron(['A',3]) + sage: face_list = incidence_matrix_to_bit_rep_of_Vrep(P.incidence_matrix()) + sage: face_list.compute_dimension() 3 Obtain the facets of a polyhedron as :class:`ListOfFaces` from a facet list:: diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx index 0454c9bc19c..be6ffbda794 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx @@ -100,7 +100,7 @@ cdef class PolyhedronFaceLattice: sage: P = polytopes.Birkhoff_polytope(3) sage: C = CombinatorialPolyhedron(P) sage: C._record_all_faces() # indirect doctests - sage: C.face_lattice() # optional - sage.combinat + sage: C.face_lattice() # needs sage.combinat Finite lattice containing 50 elements ALGORITHM: @@ -215,7 +215,7 @@ cdef class PolyhedronFaceLattice: sage: P = polytopes.cube() sage: C = CombinatorialPolyhedron(P) sage: C._record_all_faces() # indirect doctests - sage: C.face_lattice() # optional - sage.combinat + sage: C.face_lattice() # needs sage.combinat Finite lattice containing 28 elements sage: TestSuite(sage.geometry.polyhedron.combinatorial_polyhedron.polyhedron_face_lattice.PolyhedronFaceLattice).run() diff --git a/src/sage/geometry/polyhedron/constructor.py b/src/sage/geometry/polyhedron/constructor.py index 4fd1eadb2d8..f18492f584f 100644 --- a/src/sage/geometry/polyhedron/constructor.py +++ b/src/sage/geometry/polyhedron/constructor.py @@ -176,8 +176,8 @@ exact way to work with roots in Sage is the :mod:`Algebraic Real Field ` :: - sage: triangle = Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)], base_ring=AA) # optional - sage.rings.number_field sage.symbolic - sage: triangle.Hrepresentation() # optional - sage.rings.number_field sage.symbolic + sage: triangle = Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)], base_ring=AA) # needs sage.rings.number_field sage.symbolic + sage: triangle.Hrepresentation() # needs sage.rings.number_field sage.symbolic (An inequality (-1, -0.5773502691896258?) x + 1 >= 0, An inequality (1, -0.5773502691896258?) x + 0 >= 0, An inequality (0, 1.154700538379252?) x + 0 >= 0) @@ -186,12 +186,12 @@ symbolic ring element and, therefore, the polyhedron defined over the symbolic ring. This is currently not supported as SR is not exact:: - sage: Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)]) # optional - sage.symbolic + sage: Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)]) # needs sage.symbolic Traceback (most recent call last): ... ValueError: no default backend for computations with Symbolic Ring - sage: SR.is_exact() # optional - sage.symbolic + sage: SR.is_exact() # needs sage.symbolic False Even faster than all algebraic real numbers (the field ``AA``) is @@ -199,8 +199,8 @@ triangle, that would be:: sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 - 3, embedding=AA(3)**(1/2)) # optional - sage.rings.number_field - sage: Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - 3, embedding=AA(3)**(1/2)) # needs sage.rings.number_field + sage: Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # needs sage.rings.number_field A 2-dimensional polyhedron in (Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)^2 defined as the convex hull of 3 vertices @@ -220,7 +220,7 @@ A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex sage: Polyhedron(vertices = [[1.12345678901234, 2.123456789012345]]) A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex - sage: Polyhedron(vertices = [[1.123456789012345, 2.123456789012345]]) # optional - sage.rings.real_mpfr + sage: Polyhedron(vertices = [[1.123456789012345, 2.123456789012345]]) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: the only allowed inexact ring is 'RDF' with backend 'cdd' @@ -452,26 +452,28 @@ def Polyhedron(vertices=None, rays=None, lines=None, by the cyclic shifts of `(0, \pm 1, \pm (1+\sqrt(5))/2)`, cf. :wikipedia:`Regular_icosahedron`. It needs a number field:: - sage: R0. = QQ[] # optional - sage.rings.number_field - sage: R1. = NumberField(r0^2-5, embedding=AA(5)**(1/2)) # optional - sage.rings.number_field - sage: gold = (1+r1)/2 # optional - sage.rings.number_field - sage: v = [[0, 1, gold], [0, 1, -gold], [0, -1, gold], [0, -1, -gold]] # optional - sage.rings.number_field - sage: pp = Permutation((1, 2, 3)) # optional - sage.combinat sage.rings.number_field - sage: icosah = Polyhedron( # optional - sage.combinat sage.rings.number_field + sage: # needs sage.rings.number_field + sage: R0. = QQ[] + sage: R1. = NumberField(r0^2-5, embedding=AA(5)**(1/2)) + sage: gold = (1+r1)/2 + sage: v = [[0, 1, gold], [0, 1, -gold], [0, -1, gold], [0, -1, -gold]] + sage: pp = Permutation((1, 2, 3)) + sage: icosah = Polyhedron( # needs sage.combinat ....: [(pp^2).action(w) for w in v] + [pp.action(w) for w in v] + v, ....: base_ring=R1) - sage: len(icosah.faces(2)) # optional - sage.combinat sage.rings.number_field + sage: len(icosah.faces(2)) # needs sage.combinat 20 When the input contains elements of a Number Field, they require an embedding:: + sage: # needs sage.rings.number_field sage: x = polygen(ZZ, 'x') - sage: K = NumberField(x^2 - 2,'s') # optional - sage.rings.number_field - sage: s = K.0 # optional - sage.rings.number_field - sage: L = NumberField(x^3 - 2,'t') # optional - sage.rings.number_field - sage: t = L.0 # optional - sage.rings.number_field - sage: P = Polyhedron(vertices=[[0,s], [t,0]]) # optional - sage.rings.number_field + sage: K = NumberField(x^2 - 2,'s') + sage: s = K.0 + sage: L = NumberField(x^3 - 2,'t') + sage: t = L.0 + sage: P = Polyhedron(vertices=[[0,s], [t,0]]) Traceback (most recent call last): ... ValueError: invalid base ring @@ -508,12 +510,13 @@ def Polyhedron(vertices=None, rays=None, lines=None, sage: Polyhedron(o, base_ring=QQ) A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices - sage: H. = HyperplaneArrangements(QQ) # optional - sage.combinat - sage: h = x + y - 1; h # optional - sage.combinat + sage: # needs sage.combinat + sage: H. = HyperplaneArrangements(QQ) + sage: h = x + y - 1; h Hyperplane x + y - 1 - sage: Polyhedron(h, base_ring=ZZ) # optional - sage.combinat + sage: Polyhedron(h, base_ring=ZZ) A 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex and 1 line - sage: Polyhedron(h) # optional - sage.combinat + sage: Polyhedron(h) A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line .. NOTE:: @@ -567,7 +570,7 @@ def Polyhedron(vertices=None, rays=None, lines=None, Check that input with too many bits of precision returns an error (see :trac:`22552`):: - sage: Polyhedron(vertices=[(8.3319544851638732, 7.0567045956967727), # optional - sage.rings.real_mpfr + sage: Polyhedron(vertices=[(8.3319544851638732, 7.0567045956967727), # needs sage.rings.real_mpfr ....: (6.4876921900819049, 4.8435898415984129)]) Traceback (most recent call last): ... @@ -575,11 +578,11 @@ def Polyhedron(vertices=None, rays=None, lines=None, Check that setting ``base_ring`` to a ``RealField`` returns an error (see :trac:`22552`):: - sage: Polyhedron(vertices=[(8.3, 7.0), (6.4, 4.8)], base_ring=RealField(40)) # optional - sage.rings.real_mpfr + sage: Polyhedron(vertices=[(8.3, 7.0), (6.4, 4.8)], base_ring=RealField(40)) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: no default backend for computations with Real Field with 40 bits of precision - sage: Polyhedron(vertices=[(8.3, 7.0), (6.4, 4.8)], base_ring=RealField(53)) # optional - sage.rings.real_mpfr + sage: Polyhedron(vertices=[(8.3, 7.0), (6.4, 4.8)], base_ring=RealField(53)) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: no default backend for computations with Real Field with 53 bits of precision diff --git a/src/sage/geometry/polyhedron/double_description.py b/src/sage/geometry/polyhedron/double_description.py index e8aad9bcd29..089580e3146 100644 --- a/src/sage/geometry/polyhedron/double_description.py +++ b/src/sage/geometry/polyhedron/double_description.py @@ -28,10 +28,10 @@ `\RR`, for example:: sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm - sage: A = matrix(AA, [(1,0,1), (0,1,1), (-AA(2).sqrt(),-AA(3).sqrt(),1), # optional - sage.rings.number_field + sage: A = matrix(AA, [(1,0,1), (0,1,1), (-AA(2).sqrt(),-AA(3).sqrt(),1), # needs sage.rings.number_field ....: (-AA(3).sqrt(),-AA(2).sqrt(),1)]) - sage: alg = StandardAlgorithm(A) # optional - sage.rings.number_field - sage: alg.run().R # optional - sage.rings.number_field + sage: alg = StandardAlgorithm(A) + sage: alg.run().R # needs sage.rings.number_field [(-0.4177376677004119?, 0.5822623322995881?, 0.4177376677004119?), (-0.2411809548974793?, -0.2411809548974793?, 0.2411809548974793?), (0.07665629029830300?, 0.07665629029830300?, 0.2411809548974793?), @@ -411,10 +411,11 @@ def matrix_space(self, nrows, ncols): sage: DD.matrix_space(3,2) Full MatrixSpace of 3 by 2 dense matrices over Rational Field - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: A = matrix([[1,sqrt2],[2,0]]) # optional - sage.rings.number_field - sage: DD, _ = Problem(A).initial_pair() # optional - sage.rings.number_field - sage: DD.matrix_space(1,2) # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(2) + sage: A = matrix([[1,sqrt2],[2,0]]) + sage: DD, _ = Problem(A).initial_pair() + sage: DD.matrix_space(1,2) Full MatrixSpace of 1 by 2 dense matrices over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? """ @@ -597,9 +598,9 @@ def base_ring(self): EXAMPLES:: - sage: A = matrix(AA, [(1, 1), (-1, 1)]) # optional - sage.rings.number_field + sage: A = matrix(AA, [(1, 1), (-1, 1)]) # needs sage.rings.number_field sage: from sage.geometry.polyhedron.double_description import Problem - sage: Problem(A).base_ring() # optional - sage.rings.number_field + sage: Problem(A).base_ring() # needs sage.rings.number_field Algebraic Real Field """ return self._field diff --git a/src/sage/geometry/polyhedron/face.py b/src/sage/geometry/polyhedron/face.py index 64b14e39386..8a1e2dc2969 100644 --- a/src/sage/geometry/polyhedron/face.py +++ b/src/sage/geometry/polyhedron/face.py @@ -35,7 +35,7 @@ or :meth:`~sage.geometry.polyhedron.base.face_lattice` to get the whole face lattice as a poset:: - sage: P.face_lattice() # optional - sage.combinat + sage: P.face_lattice() # needs sage.combinat Finite lattice containing 28 elements The faces are printed in shorthand notation where each integer is the @@ -404,7 +404,7 @@ def ambient_Hrepresentation(self, index=None): EXAMPLES:: sage: square = polytopes.hypercube(2) - sage: for face in square.face_lattice(): # optional - sage.combinat + sage: for face in square.face_lattice(): # needs sage.combinat ....: print(face.ambient_Hrepresentation()) (An inequality (-1, 0) x + 1 >= 0, An inequality (0, -1) x + 1 >= 0, An inequality (1, 0) x + 1 >= 0, An inequality (0, 1) x + 1 >= 0) @@ -445,7 +445,7 @@ def ambient_Vrepresentation(self, index=None): EXAMPLES:: sage: square = polytopes.hypercube(2) - sage: for fl in square.face_lattice(): # optional - sage.combinat + sage: for fl in square.face_lattice(): # needs sage.combinat ....: print(fl.ambient_Vrepresentation()) () (A vertex at (1, -1),) @@ -478,14 +478,14 @@ def n_ambient_Hrepresentation(self): EXAMPLES:: sage: p = polytopes.cross_polytope(4) - sage: face = p.face_lattice()[5]; face # optional - sage.combinat + sage: face = p.face_lattice()[5]; face # needs sage.combinat A 1-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 2 vertices - sage: face.ambient_Hrepresentation() # optional - sage.combinat + sage: face.ambient_Hrepresentation() # needs sage.combinat (An inequality (1, -1, 1, -1) x + 1 >= 0, An inequality (1, 1, 1, 1) x + 1 >= 0, An inequality (1, 1, 1, -1) x + 1 >= 0, An inequality (1, -1, 1, 1) x + 1 >= 0) - sage: face.n_ambient_Hrepresentation() # optional - sage.combinat + sage: face.n_ambient_Hrepresentation() # needs sage.combinat 4 """ return len(self.ambient_Hrepresentation()) @@ -504,11 +504,11 @@ def n_ambient_Vrepresentation(self): EXAMPLES:: sage: p = polytopes.cross_polytope(4) - sage: face = p.face_lattice()[5]; face # optional - sage.combinat + sage: face = p.face_lattice()[5]; face # needs sage.combinat A 1-dimensional face of a Polyhedron in ZZ^4 defined as the convex hull of 2 vertices - sage: face.ambient_Vrepresentation() # optional - sage.combinat + sage: face.ambient_Vrepresentation() # needs sage.combinat (A vertex at (-1, 0, 0, 0), A vertex at (0, 0, -1, 0)) - sage: face.n_ambient_Vrepresentation() # optional - sage.combinat + sage: face.n_ambient_Vrepresentation() # needs sage.combinat 2 """ return len(self.ambient_Vrepresentation()) @@ -593,8 +593,8 @@ def dim(self): EXAMPLES:: - sage: fl = polytopes.dodecahedron().face_lattice() # optional - sage.combinat sage.rings.number_field - sage: sorted(x.dim() for x in fl) # optional - sage.combinat sage.rings.number_field + sage: fl = polytopes.dodecahedron().face_lattice() # needs sage.combinat sage.rings.number_field + sage: sorted(x.dim() for x in fl) # needs sage.combinat sage.rings.number_field [-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3] @@ -628,8 +628,8 @@ def _repr_(self): EXAMPLES:: sage: square = polytopes.hypercube(2) - sage: a_face = list( square.face_lattice() )[8] # optional - sage.combinat - sage: a_face.__repr__() # optional - sage.combinat + sage: a_face = list( square.face_lattice() )[8] # needs sage.combinat + sage: a_face.__repr__() # needs sage.combinat 'A 1-dimensional face of a Polyhedron in ZZ^2 defined as the convex hull of 2 vertices' """ desc = '' @@ -705,7 +705,7 @@ def ambient_vector_space(self, base_field=None): Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line sage: line.ambient_vector_space() Vector space of dimension 2 over Rational Field - sage: line.ambient_vector_space(AA) # optional - sage.rings.number_field + sage: line.ambient_vector_space(AA) # needs sage.rings.number_field Vector space of dimension 2 over Algebraic Real Field """ return self.polyhedron().ambient_vector_space(base_field=base_field) diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py index 1c788d2c1bc..a1a59cdfe65 100644 --- a/src/sage/geometry/polyhedron/library.py +++ b/src/sage/geometry/polyhedron/library.py @@ -117,7 +117,7 @@ def zero_sum_projection(d, base_ring=None): Exact computation in :class:`AA `:: - sage: zero_sum_projection(3, base_ring=AA) # optional - sage.rings.number_field + sage: zero_sum_projection(3, base_ring=AA) # needs sage.rings.number_field [ 0.7071067811865475? -0.7071067811865475? 0] [ 0.4082482904638630? 0.4082482904638630? -0.8164965809277260?] @@ -171,17 +171,17 @@ def project_points(*points, **kwds): Check that it is (almost) an isometry:: - sage: V = list(map(vector, IntegerVectors(n=5, length=3))) # optional - sage.combinat - sage: P = project_points(*V) # optional - sage.combinat - sage: for i in range(21): # optional - sage.combinat + sage: V = list(map(vector, IntegerVectors(n=5, length=3))) + sage: P = project_points(*V) + sage: for i in range(21): # needs sage.combinat ....: for j in range(21): ....: assert abs((V[i]-V[j]).norm() - (P[i]-P[j]).norm()) < 0.00001 Example with exact computation:: - sage: V = [ vector(v) for v in IntegerVectors(n=4, length=2) ] # optional - sage.combinat - sage: P = project_points(*V, base_ring=AA) # optional - sage.combinat sage.rings.number_field - sage: for i in range(len(V)): # optional - sage.combinat sage.rings.number_field + sage: V = [ vector(v) for v in IntegerVectors(n=4, length=2) ] + sage: P = project_points(*V, base_ring=AA) # needs sage.combinat sage.rings.number_field + sage: for i in range(len(V)): # needs sage.combinat sage.rings.number_field ....: for j in range(len(V)): ....: assert (V[i]-V[j]).norm() == (P[i]-P[j]).norm() @@ -515,15 +515,16 @@ def regular_polygon(self, n, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: octagon = polytopes.regular_polygon(8) # optional - sage.rings.number_field - sage: octagon # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: octagon = polytopes.regular_polygon(8) + sage: octagon A 2-dimensional polyhedron in AA^2 defined as the convex hull of 8 vertices - sage: octagon.n_vertices() # optional - sage.rings.number_field + sage: octagon.n_vertices() 8 - sage: v = octagon.volume() # optional - sage.rings.number_field - sage: v # optional - sage.rings.number_field + sage: v = octagon.volume() + sage: v 2.828427124746190? - sage: v == 2*QQbar(2).sqrt() # optional - sage.rings.number_field + sage: v == 2*QQbar(2).sqrt() True Its non exact version:: @@ -537,14 +538,16 @@ def regular_polygon(self, n, exact=True, base_ring=None, backend=None): TESTS:: - sage: octagon = polytopes.regular_polygon(8, backend='normaliz') # optional - pynormaliz sage.rings.number_field - sage: octagon # optional - pynormaliz sage.rings.number_field + sage: # optional - pynormaliz, needs sage.rings.number_field + sage: octagon = polytopes.regular_polygon(8, backend='normaliz') + sage: octagon A 2-dimensional polyhedron in AA^2 defined as the convex hull of 8 vertices - sage: octagon.n_vertices() # optional - pynormaliz sage.rings.number_field + sage: octagon.n_vertices() 8 - sage: octagon.volume() # optional - pynormaliz sage.rings.number_field + sage: octagon.volume() 2*a - sage: TestSuite(octagon).run() # long time # optional - sage.rings.number_field + sage: TestSuite(octagon).run() # long time + sage: TestSuite(polytopes.regular_polygon(5, exact=False)).run() """ n = ZZ(n) @@ -678,8 +681,8 @@ def simplex(self, dim=3, project=False, base_ring=None, backend=None): Computation in algebraic reals:: - sage: s3 = polytopes.simplex(3, project=True, base_ring=AA) # optional - sage.rings.number_field - sage: s3.volume() == sqrt(3+1) / factorial(3) # optional - sage.rings.number_field + sage: s3 = polytopes.simplex(3, project=True, base_ring=AA) # needs sage.rings.number_field + sage: s3.volume() == sqrt(3+1) / factorial(3) # needs sage.rings.number_field True TESTS:: @@ -716,47 +719,48 @@ def icosahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: ico = polytopes.icosahedron() # optional - sage.rings.number_field - sage: ico.f_vector() # optional - sage.rings.number_field + sage: ico = polytopes.icosahedron() # needs sage.rings.number_field + sage: ico.f_vector() # needs sage.rings.number_field (1, 12, 30, 20, 1) - sage: ico.volume() # optional - sage.rings.number_field + sage: ico.volume() # needs sage.rings.number_field 5/12*sqrt5 + 5/4 Its non exact version:: - sage: ico = polytopes.icosahedron(exact=False) # optional - sage.groups - sage: ico.base_ring() # optional - sage.groups + sage: ico = polytopes.icosahedron(exact=False) # needs sage.groups + sage: ico.base_ring() # needs sage.groups Real Double Field - sage: ico.volume() # known bug (trac 18214) # optional - sage.groups + sage: ico.volume() # known bug # needs sage.groups 2.181694990... A version using `AA `:: - sage: ico = polytopes.icosahedron(base_ring=AA) # long time # optional - sage.rings.number_field sage.groups - sage: ico.base_ring() # long time # optional - sage.rings.number_field sage.groups + sage: ico = polytopes.icosahedron(base_ring=AA) # long time # needs sage.groups sage.rings.number_field + sage: ico.base_ring() # long time # needs sage.groups sage.rings.number_field Algebraic Real Field - sage: ico.volume() # long time # optional - sage.rings.number_field sage.groups + sage: ico.volume() # long time # needs sage.groups sage.rings.number_field 2.181694990624913? Note that if base ring is provided it must contain the square root of `5`. Otherwise you will get an error:: - sage: polytopes.icosahedron(base_ring=QQ) # optional - sage.symbolic + sage: polytopes.icosahedron(base_ring=QQ) # needs sage.symbolic Traceback (most recent call last): ... TypeError: unable to convert 1/4*sqrt(5) + 1/4 to a rational TESTS:: - sage: ico = polytopes.icosahedron(backend='normaliz') # optional - pynormaliz sage.rings.number_field sage.groups - sage: ico.f_vector() # optional - pynormaliz sage.rings.number_field sage.groups + sage: # optional - pynormaliz, needs sage.groups sage.rings.number_field + sage: ico = polytopes.icosahedron(backend='normaliz') + sage: ico.f_vector() (1, 12, 30, 20, 1) - sage: ico.volume() # optional - pynormaliz sage.rings.number_field sage.groups + sage: ico.volume() 5/12*sqrt5 + 5/4 - sage: TestSuite(ico).run() # optional - pynormaliz sage.rings.number_field sage.groups + sage: TestSuite(ico).run() - sage: ico = polytopes.icosahedron(exact=False) # optional - sage.groups - sage: TestSuite(ico).run(skip="_test_lawrence") # optional - sage.groups + sage: ico = polytopes.icosahedron(exact=False) # needs sage.groups + sage: TestSuite(ico).run(skip="_test_lawrence") # needs sage.groups """ if base_ring is None and exact: @@ -798,31 +802,32 @@ def dodecahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: d12 = polytopes.dodecahedron() # optional - sage.rings.number_field sage.groups - sage: d12.f_vector() # optional - sage.rings.number_field sage.groups + sage: # needs sage.groups sage.rings.number_field + sage: d12 = polytopes.dodecahedron() + sage: d12.f_vector() (1, 20, 30, 12, 1) - sage: d12.volume() # optional - sage.rings.number_field sage.groups + sage: d12.volume() -176*sqrt5 + 400 - sage: numerical_approx(_) # optional - sage.rings.number_field sage.groups + sage: numerical_approx(_) 6.45203596003699 - sage: d12 = polytopes.dodecahedron(exact=False) # optional - sage.groups - sage: d12.base_ring() # optional - sage.groups + sage: d12 = polytopes.dodecahedron(exact=False) # needs sage.groups + sage: d12.base_ring() # needs sage.groups Real Double Field Here is an error with a field that does not contain `\sqrt(5)`:: - sage: polytopes.dodecahedron(base_ring=QQ) # optional - sage.symbolic sage.groups + sage: polytopes.dodecahedron(base_ring=QQ) # needs sage.groups sage.symbolic Traceback (most recent call last): ... TypeError: unable to convert 1/4*sqrt(5) + 1/4 to a rational TESTS:: - sage: d12 = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz sage.rings.number_field sage.groups - sage: d12.f_vector() # optional - pynormaliz sage.rings.number_field sage.groups + sage: d12 = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz, needs sage.groups sage.rings.number_field + sage: d12.f_vector() # optional - pynormaliz, needs sage.groups sage.rings.number_field (1, 20, 30, 12, 1) - sage: TestSuite(d12).run() # optional - pynormaliz sage.rings.number_field sage.groups + sage: TestSuite(d12).run() # optional - pynormaliz, needs sage.groups sage.rings.number_field """ return self.icosahedron(exact=exact, base_ring=base_ring, backend=backend).polar() @@ -847,17 +852,17 @@ def small_rhombicuboctahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: sr = polytopes.small_rhombicuboctahedron() # optional - sage.rings.number_field - sage: sr.f_vector() # optional - sage.rings.number_field + sage: sr = polytopes.small_rhombicuboctahedron() # needs sage.rings.number_field + sage: sr.f_vector() # needs sage.rings.number_field (1, 24, 48, 26, 1) - sage: sr.volume() # optional - sage.rings.number_field + sage: sr.volume() # needs sage.rings.number_field 80/3*sqrt2 + 32 The faces are `8` equilateral triangles and `18` squares:: - sage: sum(1 for f in sr.facets() if len(f.vertices()) == 3) # optional - sage.rings.number_field + sage: sum(1 for f in sr.facets() if len(f.vertices()) == 3) # needs sage.rings.number_field 8 - sage: sum(1 for f in sr.facets() if len(f.vertices()) == 4) # optional - sage.rings.number_field + sage: sum(1 for f in sr.facets() if len(f.vertices()) == 4) # needs sage.rings.number_field 18 Its non exact version:: @@ -871,12 +876,13 @@ def small_rhombicuboctahedron(self, exact=True, base_ring=None, backend=None): TESTS:: - sage: sr = polytopes.small_rhombicuboctahedron(backend='normaliz') # optional - sage.rings.number_field pynormaliz - sage: sr.f_vector() # optional - sage.rings.number_field pynormaliz + sage: # optional - pynormaliz, needs sage.rings.number_field + sage: sr = polytopes.small_rhombicuboctahedron(backend='normaliz') + sage: sr.f_vector() (1, 24, 48, 26, 1) - sage: sr.volume() # optional - sage.rings.number_field pynormaliz + sage: sr.volume() 80/3*sqrt2 + 32 - sage: TestSuite(sr).run() # long time # optional - sage.rings.number_field pynormaliz + sage: TestSuite(sr).run() # long time """ if base_ring is None and exact: from sage.rings.number_field.number_field import QuadraticField @@ -918,8 +924,8 @@ def great_rhombicuboctahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: gr = polytopes.great_rhombicuboctahedron() # long time ~ 3sec # optional - sage.rings.number_field - sage: gr.f_vector() # long time # optional - sage.rings.number_field + sage: gr = polytopes.great_rhombicuboctahedron() # long time # needs sage.rings.number_field + sage: gr.f_vector() # long time # needs sage.rings.number_field (1, 48, 72, 26, 1) A faster implementation is obtained by setting ``exact=False``:: @@ -1072,28 +1078,28 @@ def truncated_cube(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: co = polytopes.truncated_cube() # optional - sage.rings.number_field - sage: co.f_vector() # optional - sage.rings.number_field + sage: co = polytopes.truncated_cube() # needs sage.rings.number_field + sage: co.f_vector() # needs sage.rings.number_field (1, 24, 36, 14, 1) Its facets are 8 triangles and 6 octogons:: - sage: sum(1 for f in co.facets() if len(f.vertices()) == 3) # optional - sage.rings.number_field + sage: sum(1 for f in co.facets() if len(f.vertices()) == 3) # needs sage.rings.number_field 8 - sage: sum(1 for f in co.facets() if len(f.vertices()) == 8) # optional - sage.rings.number_field + sage: sum(1 for f in co.facets() if len(f.vertices()) == 8) # needs sage.rings.number_field 6 Some more computation:: - sage: co.volume() # optional - sage.rings.number_field + sage: co.volume() # needs sage.rings.number_field 56/3*sqrt2 - 56/3 TESTS:: - sage: co = polytopes.truncated_cube(backend='normaliz') # optional - pynormaliz sage.rings.number_field - sage: co.f_vector() # optional - pynormaliz sage.rings.number_field + sage: co = polytopes.truncated_cube(backend='normaliz') # optional - pynormaliz, needs sage.rings.number_field + sage: co.f_vector() # optional - pynormaliz # needs sage.rings.number_field (1, 24, 36, 14, 1) - sage: TestSuite(co).run() # optional - pynormaliz sage.rings.number_field + sage: TestSuite(co).run() # optional - pynormaliz # needs sage.rings.number_field """ if base_ring is None and exact: @@ -1218,28 +1224,28 @@ def truncated_octahedron(self, backend=None): EXAMPLES:: - sage: co = polytopes.truncated_octahedron() # optional - sage.combinat - sage: co.f_vector() # optional - sage.combinat + sage: co = polytopes.truncated_octahedron() + sage: co.f_vector() (1, 24, 36, 14, 1) Its facets are 6 squares and 8 hexagons:: - sage: sum(1 for f in co.facets() if len(f.vertices()) == 4) # optional - sage.combinat + sage: sum(1 for f in co.facets() if len(f.vertices()) == 4) 6 - sage: sum(1 for f in co.facets() if len(f.vertices()) == 6) # optional - sage.combinat + sage: sum(1 for f in co.facets() if len(f.vertices()) == 6) 8 Some more computation:: - sage: co.volume() # optional - sage.combinat + sage: co.volume() 32 - sage: co.ehrhart_polynomial() # optional - latte_int sage.combinat + sage: co.ehrhart_polynomial() # optional - latte_int # needs sage.combinat 32*t^3 + 18*t^2 + 6*t + 1 TESTS:: - sage: to_norm = polytopes.truncated_octahedron(backend='normaliz') # optional - pynormaliz sage.combinat - sage: TestSuite(to_norm).run() # optional - pynormaliz sage.combinat + sage: to_norm = polytopes.truncated_octahedron(backend='normaliz') # optional - pynormaliz, needs sage.combinat + sage: TestSuite(to_norm).run() # optional - pynormaliz, needs sage.combinat """ v = [(0, e, f) for e in [-1, 1] for f in [-2, 2]] v = [(xyz[sigma(1) - 1], xyz[sigma(2) - 1], xyz[sigma(3) - 1]) @@ -1313,14 +1319,17 @@ def snub_cube(self, exact=False, base_ring=None, backend=None, verbose=False): EXAMPLES:: - sage: sc_inexact = polytopes.snub_cube(exact=False); sc_inexact # optional - sage.groups + sage: # needs sage.groups + sage: sc_inexact = polytopes.snub_cube(exact=False); sc_inexact A 3-dimensional polyhedron in RDF^3 defined as the convex hull of 24 vertices - sage: sc_inexact.f_vector() # optional - sage.groups + sage: sc_inexact.f_vector() (1, 24, 60, 38, 1) - sage: sc_exact = polytopes.snub_cube(exact=True) # long time # optional - sage.groups sage.rings.number_field - sage: sc_exact.f_vector() # long time # optional - sage.groups sage.rings.number_field + + sage: # long time, needs sage.groups sage.rings.number_field + sage: sc_exact = polytopes.snub_cube(exact=True) + sage: sc_exact.f_vector() (1, 24, 60, 38, 1) - sage: sorted(sc_exact.vertices()) # long time # optional - sage.groups sage.rings.number_field + sage: sorted(sc_exact.vertices()) [A vertex at (-1, -z, -z^2), A vertex at (-1, -z^2, z), A vertex at (-1, z^2, -z), @@ -1345,13 +1354,13 @@ def snub_cube(self, exact=False, base_ring=None, backend=None, verbose=False): A vertex at (1, -z^2, -z), A vertex at (1, z^2, z), A vertex at (1, z, -z^2)] - sage: sc_exact.is_combinatorially_isomorphic(sc_inexact) # long time # optional - sage.groups sage.rings.number_field + sage: sc_exact.is_combinatorially_isomorphic(sc_inexact) True TESTS:: - sage: sc = polytopes.snub_cube(exact=True, backend='normaliz') # optional - pynormaliz sage.groups sage.rings.number_field - sage: sc.f_vector() # optional - pynormaliz sage.groups sage.rings.number_field + sage: sc = polytopes.snub_cube(exact=True, backend='normaliz') # optional - pynormaliz, needs sage.groups sage.rings.number_field + sage: sc.f_vector() # optional - pynormaliz, needs sage.groups sage.rings.number_field (1, 24, 60, 38, 1) """ @@ -1416,34 +1425,35 @@ def buckyball(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: bb = polytopes.buckyball() # long time - 6secs # optional - sage.groups sage.rings.number_field - sage: bb.f_vector() # long time # optional - sage.groups sage.rings.number_field + sage: bb = polytopes.buckyball() # long time # needs sage.groups sage.rings.number_field + sage: bb.f_vector() # long time # needs sage.groups sage.rings.number_field (1, 60, 90, 32, 1) - sage: bb.base_ring() # long time # optional - sage.groups sage.rings.number_field + sage: bb.base_ring() # long time # needs sage.groups sage.rings.number_field Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? A much faster implementation using floating point approximations:: - sage: bb = polytopes.buckyball(exact=False) # optional - sage.groups - sage: bb.f_vector() # optional - sage.groups + sage: bb = polytopes.buckyball(exact=False) # needs sage.groups + sage: bb.f_vector() # needs sage.groups (1, 60, 90, 32, 1) - sage: bb.base_ring() # optional - sage.groups + sage: bb.base_ring() # needs sage.groups Real Double Field Its facets are 5 regular pentagons and 6 regular hexagons:: - sage: sum(1 for f in bb.facets() if len(f.vertices()) == 5) # optional - sage.groups + sage: sum(1 for f in bb.facets() if len(f.vertices()) == 5) # needs sage.groups 12 - sage: sum(1 for f in bb.facets() if len(f.vertices()) == 6) # optional - sage.groups + sage: sum(1 for f in bb.facets() if len(f.vertices()) == 6) # needs sage.groups 20 TESTS:: - sage: bb = polytopes.buckyball(backend='normaliz') # optional - pynormaliz sage.groups sage.rings.number_field - sage: bb.f_vector() # optional - pynormaliz sage.groups sage.rings.number_field + sage: # optional - pynormaliz, needs sage.groups sage.rings.number_field + sage: bb = polytopes.buckyball(backend='normaliz') + sage: bb.f_vector() (1, 60, 90, 32, 1) - sage: bb.base_ring() # optional - pynormaliz sage.groups sage.rings.number_field + sage: bb.base_ring() Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? @@ -1467,26 +1477,27 @@ def icosidodecahedron(self, exact=True, backend=None): EXAMPLES:: - sage: id = polytopes.icosidodecahedron() # optional - sage.rings.number_field sage.groups - sage: id.f_vector() # optional - sage.rings.number_field sage.groups + sage: id = polytopes.icosidodecahedron() # needs sage.groups sage.rings.number_field + sage: id.f_vector() # needs sage.groups sage.rings.number_field (1, 30, 60, 32, 1) TESTS:: - sage: id = polytopes.icosidodecahedron(exact=False); id # optional - sage.rings.number_field sage.groups + sage: id = polytopes.icosidodecahedron(exact=False); id # needs sage.groups sage.rings.number_field A 3-dimensional polyhedron in RDF^3 defined as the convex hull of 30 vertices - sage: TestSuite(id).run(skip=["_test_is_combinatorially_isomorphic", # optional - sage.rings.number_field sage.groups + sage: TestSuite(id).run(skip=["_test_is_combinatorially_isomorphic", # needs sage.groups sage.rings.number_field ....: "_test_product", ....: "_test_pyramid", ....: "_test_lawrence"]) - sage: id = polytopes.icosidodecahedron(backend='normaliz') # optional - pynormaliz sage.rings.number_field sage.groups - sage: id.f_vector() # optional - pynormaliz sage.rings.number_field sage.groups + sage: # optional - pynormaliz, needs sage.groups sage.rings.number_field + sage: id = polytopes.icosidodecahedron(backend='normaliz') + sage: id.f_vector() (1, 30, 60, 32, 1) - sage: id.base_ring() # optional - pynormaliz sage.rings.number_field sage.groups + sage: id.base_ring() Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? - sage: TestSuite(id).run() # long time # optional - pynormaliz sage.rings.number_field sage.groups + sage: TestSuite(id).run() # long time """ from sage.rings.number_field.number_field import QuadraticField from itertools import product @@ -1556,13 +1567,14 @@ def icosidodecahedron_V2(self, exact=True, base_ring=None, backend=None): TESTS:: - sage: id = polytopes.icosidodecahedron_V2(backend='normaliz') # optional - pynormaliz - sage: id.f_vector() # optional - pynormaliz + sage: # optional - pynormaliz + sage: id = polytopes.icosidodecahedron_V2(backend='normaliz') + sage: id.f_vector() (1, 30, 60, 32, 1) - sage: id.base_ring() # optional - pynormaliz + sage: id.base_ring() Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? - sage: TestSuite(id).run() # long time # optional - pynormaliz + sage: TestSuite(id).run() # long time """ if base_ring is None and exact: from sage.rings.number_field.number_field import QuadraticField @@ -1605,18 +1617,18 @@ def truncated_dodecahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: td = polytopes.truncated_dodecahedron() # optional - sage.rings.number_field - sage: td.f_vector() # optional - sage.rings.number_field + sage: td = polytopes.truncated_dodecahedron() # needs sage.rings.number_field + sage: td.f_vector() # needs sage.rings.number_field (1, 60, 90, 32, 1) - sage: td.base_ring() # optional - sage.rings.number_field + sage: td.base_ring() # needs sage.rings.number_field Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? Its facets are 20 triangles and 12 regular decagons:: - sage: sum(1 for f in td.facets() if len(f.vertices()) == 3) # optional - sage.rings.number_field + sage: sum(1 for f in td.facets() if len(f.vertices()) == 3) # needs sage.rings.number_field 20 - sage: sum(1 for f in td.facets() if len(f.vertices()) == 10) # optional - sage.rings.number_field + sage: sum(1 for f in td.facets() if len(f.vertices()) == 10) # needs sage.rings.number_field 12 The faster implementation using floating point approximations does not @@ -1639,10 +1651,11 @@ def truncated_dodecahedron(self, exact=True, base_ring=None, backend=None): TESTS:: - sage: td = polytopes.truncated_dodecahedron(backend='normaliz') # optional - pynormaliz sage.rings.number_field - sage: td.f_vector() # optional - pynormaliz sage.rings.number_field + sage: # optional - pynormaliz, needs sage.rings.number_field + sage: td = polytopes.truncated_dodecahedron(backend='normaliz') + sage: td.f_vector() (1, 60, 90, 32, 1) - sage: td.base_ring() # optional - pynormaliz sage.rings.number_field + sage: td.base_ring() Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? @@ -1701,15 +1714,15 @@ def pentakis_dodecahedron(self, exact=True, base_ring=None, backend=None): A much faster implementation is obtained when setting ``exact=False``:: - sage: pd = polytopes.pentakis_dodecahedron(exact=False) # optional - sage.groups - sage: pd.n_vertices() # optional - sage.groups + sage: pd = polytopes.pentakis_dodecahedron(exact=False) # needs sage.groups + sage: pd.n_vertices() # needs sage.groups 32 - sage: pd.n_inequalities() # optional - sage.groups + sage: pd.n_inequalities() # needs sage.groups 60 The 60 are triangles:: - sage: all(len(f.vertices()) == 3 for f in pd.facets()) # optional - sage.groups + sage: all(len(f.vertices()) == 3 for f in pd.facets()) # needs sage.groups True """ return self.buckyball(exact=exact, base_ring=base_ring, backend=backend).polar() @@ -1775,7 +1788,7 @@ def rhombicosidodecahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: rid = polytopes.rhombicosidodecahedron() # long time - 6secs + sage: rid = polytopes.rhombicosidodecahedron() # long time (6secs) sage: rid.f_vector() # long time (1, 60, 120, 62, 1) sage: rid.base_ring() # long time @@ -1801,10 +1814,11 @@ def rhombicosidodecahedron(self, exact=True, base_ring=None, backend=None): TESTS:: - sage: rid = polytopes.rhombicosidodecahedron(backend='normaliz') # optional - pynormaliz - sage: rid.f_vector() # optional - pynormaliz + sage: # optional - pynormaliz + sage: rid = polytopes.rhombicosidodecahedron(backend='normaliz') + sage: rid.f_vector() (1, 60, 120, 62, 1) - sage: rid.base_ring() # optional - pynormaliz + sage: rid.base_ring() Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? @@ -1881,7 +1895,7 @@ def truncated_icosidodecahedron(self, exact=True, base_ring=None, backend=None): TESTS:: sage: ti = polytopes.truncated_icosidodecahedron(backend='normaliz') # optional - pynormaliz - sage: ti.f_vector() # optional - pynormaliz + sage: ti.f_vector() (1, 120, 180, 62, 1) sage: ti.base_ring() # optional - pynormaliz Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? @@ -2242,22 +2256,23 @@ def six_hundred_cell(self, exact=False, backend=None): EXAMPLES:: - sage: p600 = polytopes.six_hundred_cell(); p600 # optional - sage.groups + sage: p600 = polytopes.six_hundred_cell(); p600 # needs sage.groups A 4-dimensional polyhedron in RDF^4 defined as the convex hull of 120 vertices - sage: p600.f_vector() # long time ~2sec # optional - sage.groups + sage: p600.f_vector() # long time (~2sec) # needs sage.groups (1, 120, 720, 1200, 600, 1) Computation with exact coordinates is currently too long to be useful:: - sage: p600 = polytopes.six_hundred_cell(exact=True) # not tested - very long time, optional - sage.groups - sage: len(list(p600.bounded_edges())) # not tested - very long time, optional - sage.groups + sage: p600 = polytopes.six_hundred_cell(exact=True) # long time, not tested, needs sage.groups + sage: len(list(p600.bounded_edges())) # long time, not tested, needs sage.groups 720 TESTS:: - sage: p600 = polytopes.six_hundred_cell(exact=True, # optional - pynormaliz sage.groups sage.rings.number_field + sage: # optional - pynormaliz, needs sage.groups sage.rings.number_field + sage: p600 = polytopes.six_hundred_cell(exact=True, ....: backend='normaliz') - sage: len(list(p600.bounded_edges())) # long time # optional - pynormaliz sage.groups sage.rings.number_field + sage: len(list(p600.bounded_edges())) # long time 720 """ if exact: @@ -2313,8 +2328,8 @@ def grand_antiprism(self, exact=True, backend=None, verbose=False): Computation with the backend ``'normaliz'`` is instantaneous:: - sage: gap_norm = polytopes.grand_antiprism(backend='normaliz') # optional - pynormaliz sage.rings.number_field - sage: gap_norm # optional - pynormaliz sage.rings.number_field + sage: gap_norm = polytopes.grand_antiprism(backend='normaliz') # optional - pynormaliz, needs sage.rings.number_field + sage: gap_norm # optional - pynormaliz, needs sage.rings.number_field A 4-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^4 defined as the convex hull of 100 vertices @@ -2470,21 +2485,23 @@ def hypersimplex(self, dim, k, project=False, backend=None): EXAMPLES:: - sage: h_4_2 = polytopes.hypersimplex(4, 2) # optional - sage.combinat - sage: h_4_2 # optional - sage.combinat + sage: # needs sage.combinat + sage: h_4_2 = polytopes.hypersimplex(4, 2) + sage: h_4_2 A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 6 vertices - sage: h_4_2.f_vector() # optional - sage.combinat + sage: h_4_2.f_vector() (1, 6, 12, 8, 1) - sage: h_4_2.ehrhart_polynomial() # optional - latte_int sage.combinat + sage: h_4_2.ehrhart_polynomial() # optional - latte_int 2/3*t^3 + 2*t^2 + 7/3*t + 1 - sage: TestSuite(h_4_2).run() # optional - sage.combinat + sage: TestSuite(h_4_2).run() - sage: h_7_3 = polytopes.hypersimplex(7, 3, project=True) # optional - sage.combinat - sage: h_7_3 # optional - sage.combinat + sage: # needs sage.combinat + sage: h_7_3 = polytopes.hypersimplex(7, 3, project=True) + sage: h_7_3 A 6-dimensional polyhedron in RDF^6 defined as the convex hull of 35 vertices - sage: h_7_3.f_vector() # optional - sage.combinat + sage: h_7_3.f_vector() (1, 35, 210, 350, 245, 84, 14, 1) - sage: TestSuite(h_7_3).run(skip=["_test_pyramid", "_test_lawrence"]) # optional - sage.combinat + sage: TestSuite(h_7_3).run(skip=["_test_pyramid", "_test_lawrence"]) """ verts = Permutations([0] * (dim - k) + [1] * k).list() if project: @@ -2530,9 +2547,9 @@ def permutahedron(self, n, project=False, backend=None): sage: perm4 = polytopes.permutahedron(4, project=True) sage: perm4 A 3-dimensional polyhedron in RDF^3 defined as the convex hull of 24 vertices - sage: perm4.plot() # optional - sage.plot + sage: perm4.plot() # needs sage.plot Graphics3d Object - sage: perm4.graph().is_isomorphic(graphs.BubbleSortGraph(4)) # optional - sage.graphs + sage: perm4.graph().is_isomorphic(graphs.BubbleSortGraph(4)) # needs sage.graphs True As both Hrepresentation an Vrepresentation are known, the permutahedron can be set @@ -2610,35 +2627,36 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula EXAMPLES:: - sage: perm_a3 = polytopes.generalized_permutahedron(['A',3]); perm_a3 # optional - sage.combinat + sage: perm_a3 = polytopes.generalized_permutahedron(['A',3]); perm_a3 # needs sage.combinat A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 24 vertices You can put the starting point along the hyperplane of the first generator:: - sage: perm_a3_011 = polytopes.generalized_permutahedron(['A',3], [0,1,1]) # optional - sage.combinat + sage: # needs sage.combinat + sage: perm_a3_011 = polytopes.generalized_permutahedron(['A',3], [0,1,1]) sage: perm_a3_011 A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 12 vertices - sage: perm_a3_110 = polytopes.generalized_permutahedron(['A',3], [1,1,0]) # optional - sage.combinat + sage: perm_a3_110 = polytopes.generalized_permutahedron(['A',3], [1,1,0]) sage: perm_a3_110 A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 12 vertices - sage: perm_a3_110.is_combinatorially_isomorphic(perm_a3_011) # optional - sage.combinat + sage: perm_a3_110.is_combinatorially_isomorphic(perm_a3_011) True - sage: perm_a3_101 = polytopes.generalized_permutahedron(['A',3], [1,0,1]) # optional - sage.combinat + sage: perm_a3_101 = polytopes.generalized_permutahedron(['A',3], [1,0,1]) sage: perm_a3_101 A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 12 vertices - sage: perm_a3_110.is_combinatorially_isomorphic(perm_a3_101) # optional - sage.combinat + sage: perm_a3_110.is_combinatorially_isomorphic(perm_a3_101) False - sage: perm_a3_011.f_vector() # optional - sage.combinat + sage: perm_a3_011.f_vector() (1, 12, 18, 8, 1) - sage: perm_a3_101.f_vector() # optional - sage.combinat + sage: perm_a3_101.f_vector() (1, 12, 24, 14, 1) The usual output does not necessarily give a polyhedron with isometric vertex figures:: - sage: perm_a2 = polytopes.generalized_permutahedron(['A',2]) # optional - sage.combinat - sage: perm_a2.vertices() # optional - sage.combinat + sage: perm_a2 = polytopes.generalized_permutahedron(['A',2]) # needs sage.combinat + sage: perm_a2.vertices() # needs sage.combinat (A vertex at (-1, -1), A vertex at (-1, 0), A vertex at (0, -1), @@ -2648,8 +2666,8 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula It works also with Coxeter types that lead to non-rational coordinates:: - sage: perm_b3 = polytopes.generalized_permutahedron(['B',3]) # long time # optional - sage.combinat sage.rings.number_field - sage: perm_b3 # long time # optional - sage.combinat sage.rings.number_field + sage: perm_b3 = polytopes.generalized_permutahedron(['B',3]) # long time, needs sage.combinat sage.rings.number_field + sage: perm_b3 # long time, needs sage.combinat sage.rings.number_field A 3-dimensional polyhedron in (Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095?)^3 defined as the convex hull of 48 vertices @@ -2659,9 +2677,9 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula rational coordinates. We first do the computations using floating point approximations (``RDF``):: - sage: perm_a2_inexact = polytopes.generalized_permutahedron( # optional - sage.combinat + sage: perm_a2_inexact = polytopes.generalized_permutahedron( # needs sage.combinat ....: ['A',2], exact=False) - sage: sorted(perm_a2_inexact.vertices()) # optional - sage.combinat + sage: sorted(perm_a2_inexact.vertices()) # needs sage.combinat [A vertex at (-1.0, -1.0), A vertex at (-1.0, 0.0), A vertex at (0.0, -1.0), @@ -2669,9 +2687,9 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula A vertex at (1.0, 0.0), A vertex at (1.0, 1.0)] - sage: perm_a2_inexact_reg = polytopes.generalized_permutahedron( # optional - sage.combinat + sage: perm_a2_inexact_reg = polytopes.generalized_permutahedron( # needs sage.combinat ....: ['A',2], exact=False, regular=True) - sage: sorted(perm_a2_inexact_reg.vertices()) # optional - sage.combinat + sage: sorted(perm_a2_inexact_reg.vertices()) # needs sage.combinat [A vertex at (-1.0, 0.0), A vertex at (-0.5, -0.8660254038), A vertex at (-0.5, 0.8660254038), @@ -2681,9 +2699,9 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula We can do the same computation using exact arithmetic with the field ``AA``:: - sage: perm_a2_reg = polytopes.generalized_permutahedron( # optional - sage.combinat sage.rings.number_field + sage: perm_a2_reg = polytopes.generalized_permutahedron( # needs sage.combinat sage.rings.number_field ....: ['A',2], regular=True) - sage: V = sorted(perm_a2_reg.vertices()); V # random # optional - sage.combinat sage.rings.number_field + sage: V = sorted(perm_a2_reg.vertices()); V # random # needs sage.combinat sage.rings.number_field [A vertex at (-1, 0), A vertex at (-1/2, -0.866025403784439?), A vertex at (-1/2, 0.866025403784439?), @@ -2694,61 +2712,65 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula Even though the numbers look like floating point approximations, the computation is actually exact. We can clean up the display a bit using ``exactify``:: - sage: for v in V: # optional - sage.combinat sage.rings.number_field + sage: for v in V: # needs sage.combinat sage.rings.number_field ....: for x in v: ....: x.exactify() - sage: V # optional - sage.combinat sage.rings.number_field + sage: V # needs sage.combinat sage.rings.number_field [A vertex at (-1, 0), A vertex at (-1/2, -0.866025403784439?), A vertex at (-1/2, 0.866025403784439?), A vertex at (1/2, -0.866025403784439?), A vertex at (1/2, 0.866025403784439?), A vertex at (1, 0)] - sage: perm_a2_reg.is_inscribed() # optional - sage.combinat sage.rings.number_field + sage: perm_a2_reg.is_inscribed() # needs sage.combinat sage.rings.number_field True Larger examples take longer:: - sage: perm_a3_reg = polytopes.generalized_permutahedron( # long time # optional - sage.rings.number_field sage.combinat + sage: # needs sage.combinat sage.rings.number_field + sage: perm_a3_reg = polytopes.generalized_permutahedron( # long time ....: ['A',3], regular=True); perm_a3_reg A 3-dimensional polyhedron in AA^3 defined as the convex hull of 24 vertices - sage: perm_a3_reg.is_inscribed() # long time # optional - sage.rings.number_field sage.combinat + sage: perm_a3_reg.is_inscribed() # long time True - sage: perm_b3_reg = polytopes.generalized_permutahedron( # not tested # optional - sage.rings.number_field sage.combinat # long time (12sec on 64 bits) + sage: perm_b3_reg = polytopes.generalized_permutahedron( # long time (12sec on 64 bits), not tested ....: ['B',3], regular=True); perm_b3_reg A 3-dimensional polyhedron in AA^3 defined as the convex hull of 48 vertices It is faster with the backend ``'number_field'``, which internally uses an embedded number field instead of doing the computations directly with the base ring (``AA``):: - sage: perm_a3_reg_nf = polytopes.generalized_permutahedron( # optional - sage.rings.number_field sage.combinat + sage: # needs sage.combinat sage.rings.number_field + sage: perm_a3_reg_nf = polytopes.generalized_permutahedron( ....: ['A',3], regular=True, backend='number_field'); perm_a3_reg_nf A 3-dimensional polyhedron in AA^3 defined as the convex hull of 24 vertices - sage: perm_a3_reg_nf.is_inscribed() # optional - sage.rings.number_field sage.combinat + sage: perm_a3_reg_nf.is_inscribed() True - sage: perm_b3_reg_nf = polytopes.generalized_permutahedron( # long time # optional - sage.rings.number_field sage.combinat + sage: perm_b3_reg_nf = polytopes.generalized_permutahedron( # long time ....: ['B',3], regular=True, backend='number_field'); perm_b3_reg_nf A 3-dimensional polyhedron in AA^3 defined as the convex hull of 48 vertices It is even faster with the backend ``'normaliz'``:: - sage: perm_a3_reg_norm = polytopes.generalized_permutahedron( # optional - pynormaliz sage.rings.number_field sage.combinat + sage: # optional - pynormaliz, needs sage.combinat sage.rings.number_field + sage: perm_a3_reg_norm = polytopes.generalized_permutahedron( ....: ['A',3], regular=True, backend='normaliz'); perm_a3_reg_norm A 3-dimensional polyhedron in AA^3 defined as the convex hull of 24 vertices - sage: perm_a3_reg_norm.is_inscribed() # optional - pynormaliz sage.rings.number_field sage.combinat + sage: perm_a3_reg_norm.is_inscribed() True - sage: perm_b3_reg_norm = polytopes.generalized_permutahedron( # optional - pynormaliz sage.rings.number_field sage.combinat + sage: perm_b3_reg_norm = polytopes.generalized_permutahedron( ....: ['B',3], regular=True, backend='normaliz'); perm_b3_reg_norm A 3-dimensional polyhedron in AA^3 defined as the convex hull of 48 vertices The speedups from using backend ``'normaliz'`` allow us to go even further:: - sage: perm_h3 = polytopes.generalized_permutahedron( # optional - pynormaliz sage.rings.number_field sage.combinat + sage: # optional - pynormaliz, needs sage.combinat sage.rings.number_field + sage: perm_h3 = polytopes.generalized_permutahedron( ....: ['H',3], backend='normaliz'); perm_h3 A 3-dimensional polyhedron in (Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790?)^3 defined as the convex hull of 120 vertices - sage: perm_f4 = polytopes.generalized_permutahedron( # long time, optional - pynormaliz sage.rings.number_field sage.combinat + sage: perm_f4 = polytopes.generalized_permutahedron( # long time ....: ['F',4], backend='normaliz'); perm_f4 A 4-dimensional polyhedron in (Number Field in a with defining polynomial x^2 - 2 with a = 1.414213562373095?)^4 @@ -2761,7 +2783,7 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula TESTS:: - sage: TestSuite(perm_h3).run() # optional - pynormaliz sage.rings.number_field sage.combinat + sage: TestSuite(perm_h3).run() # optional - pynormaliz # needs sage.combinat sage.rings.number_field """ from sage.combinat.root_system.coxeter_group import CoxeterGroup try: @@ -3247,15 +3269,15 @@ def hypercube(self, dim, intervals=None, backend=None): sage: ls = [randint(-100,100) for _ in range(4)] sage: intervals = [[x, x+randint(1,50)] for x in ls] sage: P = polytopes.hypercube(4, intervals, backend='field') - sage: P1 = polytopes.hypercube(4, intervals, backend='ppl') # optional - pplpy - sage: assert P == P1 + sage: P1 = polytopes.hypercube(4, intervals, backend='ppl') # needs pplpy + sage: assert P == P1 # needs pplpy Check that coercion for input invervals is handled correctly:: sage: P = polytopes.hypercube(2, [[1/2, 2], [0, 1]]) sage: P = polytopes.hypercube(2, [[1/2, 2], [0, 1.0]]) - sage: P = polytopes.hypercube(2, [[1/2, 2], [0, AA(2).sqrt()]]) # optional - sage.rings.number_field - sage: P = polytopes.hypercube(2, [[1/2, 2], [0, 1.0]], backend='ppl') # optional - pplpy + sage: P = polytopes.hypercube(2, [[1/2, 2], [0, AA(2).sqrt()]]) # needs sage.rings.number_field + sage: P = polytopes.hypercube(2, [[1/2, 2], [0, 1.0]], backend='ppl') # needs pplpy Traceback (most recent call last): ... ValueError: specified backend ppl cannot handle the intervals @@ -3357,7 +3379,7 @@ def cube(self, intervals=None, backend=None): (1, 8, 12, 6, 1) sage: c.volume() 8 - sage: c.plot() # optional - sage.plot + sage: c.plot() # needs sage.plot Graphics3d Object Return the `0/1`-cube:: @@ -3441,16 +3463,16 @@ def parallelotope(self, generators, backend=None): sage: polytopes.parallelotope([[1,2,3,4], [0,1,0,7], [3,1,0,2], [0,0,1,0]]) A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 16 vertices - sage: K = QuadraticField(2, 'sqrt2') # optional - sage.rings.number_field - sage: sqrt2 = K.gen() # optional - sage.rings.number_field - sage: P = polytopes.parallelotope([(1, sqrt2), (1, -1)]); P # optional - sage.rings.number_field + sage: K = QuadraticField(2, 'sqrt2') # needs sage.rings.number_field + sage: sqrt2 = K.gen() # needs sage.rings.number_field + sage: P = polytopes.parallelotope([(1, sqrt2), (1, -1)]); P # needs sage.rings.number_field A 2-dimensional polyhedron in (Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?)^2 defined as the convex hull of 4 vertices TESTS:: - sage: TestSuite(P).run() # optional - sage.rings.number_field + sage: TestSuite(P).run() # needs sage.rings.number_field """ from sage.modules.free_module_element import vector generators = [vector(v) for v in generators] diff --git a/src/sage/geometry/polyhedron/misc.py b/src/sage/geometry/polyhedron/misc.py index ad0ad961bf1..b47e51f79b8 100644 --- a/src/sage/geometry/polyhedron/misc.py +++ b/src/sage/geometry/polyhedron/misc.py @@ -30,7 +30,7 @@ def _to_space_separated_string(l, base_ring=None): sage: import sage.geometry.polyhedron.misc as P sage: P._to_space_separated_string([2,3]) '2 3' - sage: P._to_space_separated_string([2, 1/5], RDF) # optional - sage.rings.real_double + sage: P._to_space_separated_string([2, 1/5], RDF) # needs sage.rings.real_double '2.0 0.2' """ if base_ring: diff --git a/src/sage/geometry/polyhedron/palp_database.py b/src/sage/geometry/polyhedron/palp_database.py index 70864270966..29b729cec18 100644 --- a/src/sage/geometry/polyhedron/palp_database.py +++ b/src/sage/geometry/polyhedron/palp_database.py @@ -5,7 +5,7 @@ EXAMPLES:: sage: from sage.geometry.polyhedron.palp_database import PALPreader - sage: for lp in PALPreader(2): + sage: for lp in PALPreader(2): # needs sage.graphs ....: cone = Cone([(1,r[0],r[1]) for r in lp.vertices()]) ....: fan = Fan([cone]) ....: X = ToricVariety(fan) diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 739a4e3edbb..92691fab081 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -64,7 +64,7 @@ def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, * EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra - sage: Polyhedra(AA, 3) # optional - sage.rings.number_field + sage: Polyhedra(AA, 3) # needs sage.rings.number_field Polyhedra in AA^3 sage: Polyhedra(ZZ, 3) Polyhedra in ZZ^3 @@ -96,34 +96,34 @@ def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, * TESTS:: - sage: Polyhedra(RR, 3, backend='field') # optional - sage.rings.real_mpfr + sage: Polyhedra(RR, 3, backend='field') # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: the 'field' backend for polyhedron cannot be used with non-exact fields - sage: Polyhedra(RR, 3) # optional - sage.rings.real_mpfr + sage: Polyhedra(RR, 3) # needs sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: no default backend for computations with Real Field with 53 bits of precision - sage: Polyhedra(QQ[I], 2) # optional - sage.rings.number_field + sage: Polyhedra(QQ[I], 2) # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: invalid base ring: Number Field in I with defining polynomial x^2 + 1 with I = 1*I cannot be coerced to a real field - sage: Polyhedra(AA, 3, backend='polymake') # optional - jupymake sage.rings.number_field + sage: Polyhedra(AA, 3, backend='polymake') # optional - jupymake # needs sage.rings.number_field Traceback (most recent call last): ... ValueError: the 'polymake' backend for polyhedron cannot be used with Algebraic Real Field - sage: Polyhedra(QQ, 2, backend='normaliz') # optional - pynormaliz + sage: Polyhedra(QQ, 2, backend='normaliz') Polyhedra in QQ^2 - sage: Polyhedra(SR, 2, backend='normaliz') # optional - pynormaliz sage.symbolic + sage: Polyhedra(SR, 2, backend='normaliz') # optional - pynormaliz # needs sage.symbolic Polyhedra in (Symbolic Ring)^2 - sage: SCR = SR.subring(no_variables=True) # optional - sage.symbolic - sage: Polyhedra(SCR, 2, backend='normaliz') # optional - pynormaliz sage.symbolic + sage: SCR = SR.subring(no_variables=True) # needs sage.symbolic + sage: Polyhedra(SCR, 2, backend='normaliz') # optional - pynormaliz # needs sage.symbolic Polyhedra in (Symbolic Constants Subring)^2 - sage: Polyhedra(SCR, 2, backend='number_field') # optional - sage.symbolic + sage: Polyhedra(SCR, 2, backend='number_field') # needs sage.symbolic Polyhedra in (Symbolic Constants Subring)^2 """ @@ -272,13 +272,14 @@ def list(self): sage: P.cardinality() +Infinity - sage: P = Polyhedra(AA, 0) # optional - sage.rings.number_field - sage: P.category() # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: P = Polyhedra(AA, 0) + sage: P.category() Category of finite enumerated polyhedral sets over Algebraic Real Field - sage: P.list() # optional - sage.rings.number_field + sage: P.list() [The empty polyhedron in AA^0, A 0-dimensional polyhedron in AA^0 defined as the convex hull of 1 vertex] - sage: P.cardinality() # optional - sage.rings.number_field + sage: P.cardinality() 2 """ if self.ambient_dim(): @@ -516,8 +517,8 @@ def _repr_base_ring(self): sage: Polyhedra(QQ, 3)._repr_base_ring() 'QQ' sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 - 3, embedding=AA(3).sqrt()) # optional - sage.rings.number_field - sage: Polyhedra(K, 4)._repr_base_ring() # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - 3, embedding=AA(3).sqrt()) # needs sage.rings.number_field + sage: Polyhedra(K, 4)._repr_base_ring() # needs sage.rings.number_field '(Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)' """ @@ -551,8 +552,8 @@ def _repr_ambient_module(self): sage: Polyhedra(QQ, 3)._repr_ambient_module() 'QQ^3' sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^2 - 3, embedding=AA(3).sqrt()) # optional - sage.rings.number_field - sage: Polyhedra(K, 4)._repr_ambient_module() # optional - sage.rings.number_field + sage: K. = NumberField(x^2 - 3, embedding=AA(3).sqrt()) # needs sage.rings.number_field + sage: Polyhedra(K, 4)._repr_ambient_module() # needs sage.rings.number_field '(Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)^4' """ s = self._repr_base_ring() @@ -607,13 +608,14 @@ def _element_constructor_(self, *args, **kwds): Check that :trac:`21270` is fixed:: - sage: poly = polytopes.regular_polygon(7) # optional - sage.rings.number_field - sage: lp, x = poly.to_linear_program(solver='InteractiveLP', # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: poly = polytopes.regular_polygon(7) + sage: lp, x = poly.to_linear_program(solver='InteractiveLP', ....: return_variable=True) - sage: lp.set_objective(x[0] + x[1]) # optional - sage.rings.number_field - sage: b = lp.get_backend() # optional - sage.rings.number_field - sage: P = b.interactive_lp_problem() # optional - sage.rings.number_field - sage: p = P.plot() # optional - sage.plot sage.rings.number_field + sage: lp.set_objective(x[0] + x[1]) + sage: b = lp.get_backend() + sage: P = b.interactive_lp_problem() + sage: p = P.plot() # needs sage.plot sage: Q = Polyhedron(ieqs=[[-499999, 1000000], [1499999, -1000000]]) sage: P = Polyhedron(ieqs=[[0, 1.0], [1.0, -1.0]], base_ring=RDF) @@ -635,11 +637,12 @@ def _element_constructor_(self, *args, **kwds): When the parent of the object is not ``self``, the default is not to copy:: - sage: Q = P.base_extend(AA) # optional - sage.rings.number_field - sage: q = Q._element_constructor_(p) # optional - sage.rings.number_field - sage: q is p # optional - sage.rings.number_field + sage: # needs sage.rings.number_field + sage: Q = P.base_extend(AA) + sage: q = Q._element_constructor_(p) + sage: q is p False - sage: q = Q._element_constructor_(p, copy=False) # optional - sage.rings.number_field + sage: q = Q._element_constructor_(p, copy=False) Traceback (most recent call last): ... ValueError: you need to make a copy when changing the parent @@ -726,10 +729,10 @@ def _element_constructor_polyhedron(self, polyhedron, **kwds): sage: P(p) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices - sage: P = Polyhedra(AA, 3, backend='field') # optional - sage.rings.number_field + sage: P = Polyhedra(AA, 3, backend='field') # needs sage.rings.number_field sage: vertices = [(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)] - sage: p = Polyhedron(vertices=vertices) # optional - sage.rings.number_field - sage: P(p) # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=vertices) + sage: P(p) # needs sage.rings.number_field A 3-dimensional polyhedron in AA^3 defined as the convex hull of 4 vertices """ Vrep = None @@ -866,15 +869,15 @@ def _coerce_base_ring(self, other): Test that :trac:`28770` is fixed:: sage: z = QQ['z'].0 - sage: K = NumberField(z^2 - 2, 's') # optional - sage.rings.number_field - sage: triangle_QQ._coerce_base_ring(K) # optional - sage.rings.number_field + sage: K = NumberField(z^2 - 2, 's') # needs sage.rings.number_field + sage: triangle_QQ._coerce_base_ring(K) # needs sage.rings.number_field Number Field in s with defining polynomial z^2 - 2 - sage: triangle_QQ._coerce_base_ring(K.gen()) # optional - sage.rings.number_field + sage: triangle_QQ._coerce_base_ring(K.gen()) # needs sage.rings.number_field Number Field in s with defining polynomial z^2 - 2 sage: z = QQ['z'].0 - sage: K = NumberField(z^2 - 2, 's') # optional - sage.rings.number_field - sage: K.gen() * polytopes.simplex(backend='field') # optional - sage.rings.number_field + sage: K = NumberField(z^2 - 2, 's') # needs sage.rings.number_field + sage: K.gen() * polytopes.simplex(backend='field') # needs sage.rings.number_field A 3-dimensional polyhedron in (Number Field in s with defining polynomial z^2 - 2)^4 defined as the convex hull of 4 vertices @@ -1286,9 +1289,9 @@ def does_backend_handle_base_ring(base_ring, backend): sage: from sage.geometry.polyhedron.parent import does_backend_handle_base_ring sage: does_backend_handle_base_ring(QQ, 'ppl') True - sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'ppl') # optional - sage.rings.number_field sage.symbolic + sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'ppl') # needs sage.rings.number_field sage.symbolic False - sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'field') # optional - sage.rings.number_field sage.symbolic + sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'field') # needs sage.rings.number_field sage.symbolic True """ try: diff --git a/src/sage/geometry/polyhedron/plot.py b/src/sage/geometry/polyhedron/plot.py index 472ab1cf8c2..b6bb235b711 100644 --- a/src/sage/geometry/polyhedron/plot.py +++ b/src/sage/geometry/polyhedron/plot.py @@ -346,23 +346,24 @@ def __init__(self, polyhedron, proj=projection_func_identity): EXAMPLES:: - sage: p = polytopes.icosahedron(exact=False) # optional - sage.groups + sage: # needs sage.groups + sage: p = polytopes.icosahedron(exact=False) sage: from sage.geometry.polyhedron.plot import Projection - sage: Projection(p) # optional - sage.groups + sage: Projection(p) The projection of a polyhedron into 3 dimensions sage: def pr_12(x): return [x[1],x[2]] - sage: Projection(p, pr_12) # optional - sage.groups + sage: Projection(p, pr_12) The projection of a polyhedron into 2 dimensions - sage: Projection(p, lambda x: [x[1],x[2]] ) # another way of doing the same projection # optional - sage.groups + sage: Projection(p, lambda x: [x[1],x[2]] ) # another way of doing the same projection The projection of a polyhedron into 2 dimensions - sage: _.plot() # plot of the projected icosahedron in 2d # optional - sage.plot # optional - sage.groups + sage: _.plot() # plot of the projected icosahedron in 2d # needs sage.plot Graphics object consisting of 51 graphics primitives - sage: proj = Projection(p) # optional - sage.groups - sage: proj.stereographic([1,2,3]) # optional - sage.groups + sage: proj = Projection(p) + sage: proj.stereographic([1,2,3]) The projection of a polyhedron into 2 dimensions - sage: proj.plot() # optional - sage.plot # optional - sage.groups + sage: proj.plot() # needs sage.plot Graphics object consisting of 51 graphics primitives - sage: TestSuite(proj).run(skip='_test_pickling') # optional - sage.groups + sage: TestSuite(proj).run(skip='_test_pickling') """ self.parent_polyhedron = polyhedron self.coords = Sequence([]) @@ -411,12 +412,13 @@ def __call__(self, proj=projection_func_identity): EXAMPLES:: - sage: p = polytopes.icosahedron(exact=False) # optional - sage.groups + sage: # needs sage.groups + sage: p = polytopes.icosahedron(exact=False) sage: from sage.geometry.polyhedron.plot import Projection - sage: pproj = Projection(p) # optional - sage.groups + sage: pproj = Projection(p) sage: from sage.geometry.polyhedron.plot import ProjectionFuncStereographic - sage: pproj_stereo = pproj.__call__(proj=ProjectionFuncStereographic([1, 2, 3])) # optional - sage.groups - sage: sorted(pproj_stereo.polygons) # optional - sage.groups + sage: pproj_stereo = pproj.__call__(proj=ProjectionFuncStereographic([1, 2, 3])) + sage: sorted(pproj_stereo.polygons) [[2, 0, 9], [3, 1, 10], [4, 0, 8], @@ -435,11 +437,12 @@ def identity(self): EXAMPLES:: - sage: p = polytopes.icosahedron(exact=False) # optional - sage.groups + sage: # needs sage.groups + sage: p = polytopes.icosahedron(exact=False) sage: from sage.geometry.polyhedron.plot import Projection - sage: pproj = Projection(p) # optional - sage.groups - sage: ppid = pproj.identity() # optional - sage.groups - sage: ppid.dimension # optional - sage.groups + sage: pproj = Projection(p) + sage: ppid = pproj.identity() + sage: ppid.dimension 3 """ return self(projection_func_identity) @@ -458,7 +461,7 @@ def stereographic(self, projection_point=None): sage: from sage.geometry.polyhedron.plot import Projection sage: proj = Projection(polytopes.buckyball()); proj # long time The projection of a polyhedron into 3 dimensions - sage: proj.stereographic([5,2,3]).plot() # long time # optional - sage.plot + sage: proj.stereographic([5,2,3]).plot() # long time # needs sage.plot Graphics object consisting of 123 graphics primitives sage: Projection(polytopes.twenty_four_cell()).stereographic([2,0,0,0]) The projection of a polyhedron into 3 dimensions @@ -495,7 +498,7 @@ def schlegel(self, facet=None, position=None): sage: from sage.geometry.polyhedron.plot import Projection sage: Projection(cube4).schlegel() The projection of a polyhedron into 3 dimensions - sage: _.plot() # optional - sage.plot + sage: _.plot() # needs sage.plot Graphics3d Object The 4-cube with a truncated vertex seen into the resulting tetrahedron @@ -504,14 +507,14 @@ def schlegel(self, facet=None, position=None): sage: tcube4 = cube4.face_truncation(cube4.faces(0)[0]) sage: tcube4.facets()[4] A 3-dimensional face of a Polyhedron in QQ^4 defined as the convex hull of 4 vertices - sage: into_tetra = Projection(tcube4).schlegel(tcube4.facets()[4]) # optional - sage.symbolic - sage: into_tetra.plot() # optional - sage.plot sage.symbolic + sage: into_tetra = Projection(tcube4).schlegel(tcube4.facets()[4]) # needs sage.symbolic + sage: into_tetra.plot() # needs sage.plot sage.symbolic Graphics3d Object Taking a larger value for the position changes the image:: - sage: into_tetra_far = Projection(tcube4).schlegel(tcube4.facets()[4], 4) # optional - sage.symbolic - sage: into_tetra_far.plot() # optional - sage.plot sage.symbolic + sage: into_tetra_far = Projection(tcube4).schlegel(tcube4.facets()[4], 4) # needs sage.symbolic + sage: into_tetra_far.plot() # needs sage.plot sage.symbolic Graphics3d Object A value which is too large or negative give a projection point that @@ -917,8 +920,8 @@ def render_points_1d(self, **kwds): sage: cube1 = polytopes.hypercube(1) sage: proj = cube1.projection() - sage: points = proj.render_points_1d() # optional - sage.plot - sage: points._objects # optional - sage.plot + sage: points = proj.render_points_1d() # needs sage.plot + sage: points._objects # needs sage.plot [Point set defined by 2 point(s)] """ return point2d([c + [0] for c in self.coordinates_of(self.points)], **kwds) @@ -938,8 +941,8 @@ def render_line_1d(self, **kwds): EXAMPLES:: - sage: outline = polytopes.hypercube(1).projection().render_line_1d() # optional - sage.plot - sage: outline._objects[0] # optional - sage.plot + sage: outline = polytopes.hypercube(1).projection().render_line_1d() # needs sage.plot + sage: outline._objects[0] # needs sage.plot Line defined by 2 points """ if len(self.lines) == 0: @@ -956,10 +959,11 @@ def render_points_2d(self, **kwds): EXAMPLES:: - sage: hex = polytopes.regular_polygon(6) # optional - sage.rings.number_field - sage: proj = hex.projection() # optional - sage.rings.number_field - sage: hex_points = proj.render_points_2d() # optional - sage.plot sage.rings.number_field - sage: hex_points._objects # optional - sage.plot sage.rings.number_field + sage: # needs sage.rings.number_field + sage: hex = polytopes.regular_polygon(6) + sage: proj = hex.projection() + sage: hex_points = proj.render_points_2d() # needs sage.plot + sage: hex_points._objects # needs sage.plot [Point set defined by 6 point(s)] """ return point2d(self.coordinates_of(self.points), **kwds) @@ -970,9 +974,9 @@ def render_outline_2d(self, **kwds): EXAMPLES:: - sage: penta = polytopes.regular_polygon(5) # optional - sage.rings.number_field - sage: outline = penta.projection().render_outline_2d() # optional - sage.plot sage.rings.number_field - sage: outline._objects[0] # optional - sage.plot sage.rings.number_field + sage: penta = polytopes.regular_polygon(5) # needs sage.rings.number_field + sage: outline = penta.projection().render_outline_2d() # needs sage.plot sage.rings.number_field + sage: outline._objects[0] # needs sage.plot sage.rings.number_field Line defined by 2 points """ wireframe = [] @@ -993,8 +997,8 @@ def render_fill_2d(self, **kwds): sage: cps = [i^3 for i in srange(-2, 2, 1/5)] sage: p = Polyhedron(vertices=[[(t^2-1)/(t^2+1), 2*t/(t^2+1)] for t in cps]) sage: proj = p.projection() - sage: filled_poly = proj.render_fill_2d() # optional - sage.plot - sage: filled_poly.axes_width() # optional - sage.plot + sage: filled_poly = proj.render_fill_2d() # needs sage.plot + sage: filled_poly.axes_width() # needs sage.plot 0.8 """ poly = [polygon2d(self.coordinates_of(p), **kwds) @@ -1009,8 +1013,8 @@ def render_vertices_3d(self, **kwds): sage: p = polytopes.cross_polytope(3) sage: proj = p.projection() - sage: verts = proj.render_vertices_3d() # optional - sage.plot - sage: verts.bounding_box() # optional - sage.plot + sage: verts = proj.render_vertices_3d() # needs sage.plot + sage: verts.bounding_box() # needs sage.plot ((-1.0, -1.0, -1.0), (1.0, 1.0, 1.0)) """ return point3d(self.coordinates_of(self.points), **kwds) @@ -1023,8 +1027,8 @@ def render_wireframe_3d(self, **kwds): sage: cube = polytopes.hypercube(3) sage: cube_proj = cube.projection() - sage: wire = cube_proj.render_wireframe_3d() # optional - sage.plot - sage: print(wire.tachyon().split('\n')[77]) # for testing # optional - sage.plot + sage: wire = cube_proj.render_wireframe_3d() # needs sage.plot + sage: print(wire.tachyon().split('\n')[77]) # for testing # needs sage.plot FCylinder base 1.0 1.0 -1.0 apex -1.0 1.0 -1.0 rad 0.005 texture... """ wireframe = [] @@ -1043,8 +1047,8 @@ def render_solid_3d(self, **kwds): EXAMPLES:: sage: p = polytopes.hypercube(3).projection() - sage: p_solid = p.render_solid_3d(opacity=.7) # optional - sage.plot - sage: type(p_solid) # optional - sage.plot + sage: p_solid = p.render_solid_3d(opacity=.7) # needs sage.plot + sage: type(p_solid) # needs sage.plot """ polys = self.polygons @@ -1074,10 +1078,10 @@ def render_0d(self, point_opts=None, line_opts=None, polygon_opts=None): EXAMPLES:: - sage: print(Polyhedron([]).projection().render_0d().description()) # optional - sage.plot + sage: print(Polyhedron([]).projection().render_0d().description()) # needs sage.plot sage: P = Polyhedron(ieqs=[(1,)]) - sage: print(P.projection().render_0d().description()) # optional - sage.plot + sage: print(P.projection().render_0d().description()) # needs sage.plot Point set defined by 1 point(s): [(0.0, 0.0)] """ if point_opts is None: @@ -1106,7 +1110,7 @@ def render_1d(self, point_opts=None, line_opts=None, polygon_opts=None): EXAMPLES:: - sage: Polyhedron([(0,), (1,)]).projection().render_1d() # optional - sage.plot + sage: Polyhedron([(0,), (1,)]).projection().render_1d() # needs sage.plot Graphics object consisting of 2 graphics primitives """ plt = Graphics() @@ -1138,7 +1142,7 @@ def render_2d(self, point_opts=None, line_opts=None, polygon_opts=None): sage: q3 = p3.projection() sage: p4 = Polyhedron(vertices=[[2,0]], rays=[[1,-1]], lines=[[1,1]]) sage: q4 = p4.projection() - sage: q1.plot() + q2.plot() + q3.plot() + q4.plot() # optional - sage.plot + sage: q1.plot() + q2.plot() + q3.plot() + q4.plot() # needs sage.plot Graphics object consisting of 18 graphics primitives """ plt = Graphics() @@ -1171,31 +1175,32 @@ def render_3d(self, point_opts=None, line_opts=None, polygon_opts=None): sage: p2 = Polyhedron(vertices=[[2,0,0], [0,2,0], [0,0,2]]) sage: p3 = Polyhedron(vertices=[[1,0,0], [0,1,0], [0,0,1]], ....: rays=[[-1,-1,-1]]) - sage: (p1.projection().plot() + p2.projection().plot() # optional - sage.plot + sage: (p1.projection().plot() + p2.projection().plot() # needs sage.plot ....: + p3.projection().plot()) Graphics3d Object It correctly handles various degenerate cases:: - sage: Polyhedron(lines=[[1,0,0], [0,1,0], [0,0,1]]).plot() # whole space # optional - sage.plot + sage: # needs sage.plot + sage: Polyhedron(lines=[[1,0,0], [0,1,0], [0,0,1]]).plot() # whole space Graphics3d Object - sage: Polyhedron(vertices=[[1,1,1]], rays=[[1,0,0]], # optional - sage.plot + sage: Polyhedron(vertices=[[1,1,1]], rays=[[1,0,0]], ....: lines=[[0,1,0], [0,0,1]]).plot() # half space Graphics3d Object - sage: Polyhedron(lines=[[0,1,0], [0,0,1]], # optional - sage.plot + sage: Polyhedron(lines=[[0,1,0], [0,0,1]], ....: vertices=[[1,1,1]]).plot() # R^2 in R^3 Graphics3d Object - sage: Polyhedron(rays=[[0,1,0], [0,0,1]], # quadrant wedge in R^2 # optional - sage.plot + sage: Polyhedron(rays=[[0,1,0], [0,0,1]], # quadrant wedge in R^2 ....: lines=[[1,0,0]]).plot() Graphics3d Object - sage: Polyhedron(rays=[[0,1,0]], # upper half plane in R^3 # optional - sage.plot + sage: Polyhedron(rays=[[0,1,0]], # upper half plane in R^3 ....: lines=[[1,0,0]]).plot() Graphics3d Object - sage: Polyhedron(lines=[[1,0,0]]).plot() # R^1 in R^2 # optional - sage.plot + sage: Polyhedron(lines=[[1,0,0]]).plot() # R^1 in R^2 Graphics3d Object - sage: Polyhedron(rays=[[0,1,0]]).plot() # Half-line in R^3 # optional - sage.plot + sage: Polyhedron(rays=[[0,1,0]]).plot() # Half-line in R^3 Graphics3d Object - sage: Polyhedron(vertices=[[1,1,1]]).plot() # point in R^3 # optional - sage.plot + sage: Polyhedron(vertices=[[1,1,1]]).plot() # point in R^3 Graphics3d Object The origin is not included, if it is not in the polyhedron (:trac:`23555`):: @@ -1203,13 +1208,13 @@ def render_3d(self, point_opts=None, line_opts=None, polygon_opts=None): sage: Q = Polyhedron([[100],[101]]) sage: P = Q*Q*Q; P A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices - sage: p = P.plot() # optional - sage.plot - sage: p.bounding_box() # optional - sage.plot + sage: p = P.plot() # needs sage.plot + sage: p.bounding_box() # needs sage.plot ((100.0, 100.0, 100.0), (101.0, 101.0, 101.0)) Plot 3d polytope with rainbow colors:: - sage: polytopes.hypercube(3).plot(polygon='rainbow', alpha=0.4) # optional - sage.plot + sage: polytopes.hypercube(3).plot(polygon='rainbow', alpha=0.4) # needs sage.plot Graphics3d Object """ pplt = None @@ -1300,12 +1305,13 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, EXAMPLES:: - sage: P1 = polytopes.small_rhombicuboctahedron() # optional - sage.rings.number_field - sage: Image1 = P1.projection().tikz([1,3,5], 175, scale=4, # optional - sage.rings.number_field + sage: # needs sage.plot sage.rings.number_field + sage: P1 = polytopes.small_rhombicuboctahedron() + sage: Image1 = P1.projection().tikz([1,3,5], 175, scale=4, ....: output_type='TikzPicture') - sage: type(Image1) # optional - sage.rings.number_field + sage: type(Image1) - sage: Image1 # optional - sage.rings.number_field + sage: Image1 \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -1322,10 +1328,10 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% \end{tikzpicture} \end{document} - sage: _ = Image1.tex('polytope-tikz1.tex') # not tested # optional - sage.rings.number_field - sage: _ = Image1.png('polytope-tikz1.png') # not tested # optional - sage.rings.number_field - sage: _ = Image1.pdf('polytope-tikz1.pdf') # not tested # optional - sage.rings.number_field - sage: _ = Image1.svg('polytope-tikz1.svg') # not tested # optional - sage.rings.number_field + sage: _ = Image1.tex('polytope-tikz1.tex') # not tested + sage: _ = Image1.png('polytope-tikz1.png') # not tested + sage: _ = Image1.pdf('polytope-tikz1.pdf') # not tested + sage: _ = Image1.svg('polytope-tikz1.svg') # not tested A second example:: @@ -1354,6 +1360,7 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, The second example using a LatexExpr as output type:: + sage: # needs sage.plot sage: Image2 = P2.projection().tikz(scale=3, edge_color='blue!95!black', ....: facet_color='orange!95!black', opacity=0.4, ....: vertex_color='yellow', axis=True, @@ -1365,19 +1372,20 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, [scale=3.000000, back/.style={loosely dotted, thin}, edge/.style={color=blue!95!black, thick}, - sage: with open('polytope-tikz2.tex', 'w') as f: # not tested + sage: with open('polytope-tikz2.tex', 'w') as f: # not tested ....: _ = f.write(Image2) A third example:: + sage: # needs sage.plot sage: P3 = Polyhedron(vertices=[[-1, -1, 2], [-1, 2, -1], [2, -1, -1]]); P3 A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 3 vertices - sage: Image3 = P3.projection().tikz([0.5, -1, -0.1], 55, scale=3, # optional - sage.plot + sage: Image3 = P3.projection().tikz([0.5, -1, -0.1], 55, scale=3, ....: edge_color='blue!95!black', ....: facet_color='orange!95!black', opacity=0.7, ....: vertex_color='yellow', axis=True, ....: output_type='TikzPicture') - sage: Image3 # optional - sage.plot + sage: Image3 \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -1394,10 +1402,10 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% \end{tikzpicture} \end{document} - sage: _ = Image3.tex('polytope-tikz3.tex') # not tested # optional - sage.plot - sage: _ = Image3.png('polytope-tikz3.png') # not tested # optional - sage.plot - sage: _ = Image3.pdf('polytope-tikz3.pdf') # not tested # optional - sage.plot - sage: _ = Image3.svg('polytope-tikz3.svg') # not tested # optional - sage.plot + sage: _ = Image3.tex('polytope-tikz3.tex') # not tested + sage: _ = Image3.png('polytope-tikz3.png') # not tested + sage: _ = Image3.pdf('polytope-tikz3.pdf') # not tested + sage: _ = Image3.svg('polytope-tikz3.svg') # not tested A fourth example:: @@ -1618,26 +1626,26 @@ def _tikz_2d_in_3d(self, view, angle, scale, edge_color, facet_color, EXAMPLES:: - sage: P = Polyhedron(vertices=[[-1, -1, 2], [-1, 2, -1], [2, -1, -1]]) - sage: P + sage: # needs sage.plot + sage: P = Polyhedron(vertices=[[-1, -1, 2], [-1, 2, -1], [2, -1, -1]]); P A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 3 vertices - sage: Image = P.projection()._tikz_2d_in_3d(view=[0.5, -1, -0.5], angle=55, scale=3, # optional - sage.plot + sage: Image = P.projection()._tikz_2d_in_3d(view=[0.5, -1, -0.5], angle=55, scale=3, ....: edge_color='blue!95!black', facet_color='orange', ....: opacity=0.5, vertex_color='yellow', axis=True) - sage: print('\n'.join(Image.splitlines()[:4])) # optional - sage.plot + sage: print('\n'.join(Image.splitlines()[:4])) \begin{tikzpicture}% [x={(0.644647cm, -0.476559cm)}, y={(0.192276cm, 0.857859cm)}, z={(-0.739905cm, -0.192276cm)}, - sage: with open('polytope-tikz3.tex', 'w') as f: # not tested # optional - sage.plot + sage: with open('polytope-tikz3.tex', 'w') as f: # not tested ....: _ = f.write(Image) :: sage: p = Polyhedron(vertices=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]) sage: proj = p.projection() - sage: Img = proj.tikz([1, 1, 1], 130, axis=True, output_type='LatexExpr') # optional - sage.plot - sage: print('\n'.join(Img.splitlines()[12:21])) # optional - sage.plot + sage: Img = proj.tikz([1, 1, 1], 130, axis=True, output_type='LatexExpr') # needs sage.plot + sage: print('\n'.join(Img.splitlines()[12:21])) # needs sage.plot %% with the command: ._tikz_2d_in_3d and parameters: %% view = [1, 1, 1] %% angle = 130 @@ -1772,28 +1780,30 @@ def _tikz_3d_in_3d(self, view, angle, scale, edge_color, EXAMPLES:: - sage: P = polytopes.small_rhombicuboctahedron() # optional - sage.rings.number_field - sage: Image = P.projection()._tikz_3d_in_3d([3, 7, 5], 100, scale=3, # optional - sage.rings.number_field + sage: # needs sage.plot sage.rings.number_field + sage: P = polytopes.small_rhombicuboctahedron() + sage: Image = P.projection()._tikz_3d_in_3d([3, 7, 5], 100, scale=3, ....: edge_color='blue', facet_color='orange', ....: opacity=0.5, vertex_color='green', axis=True) - sage: type(Image) # optional - sage.rings.number_field + sage: type(Image) - sage: print('\n'.join(Image.splitlines()[:4])) # optional - sage.rings.number_field + sage: print('\n'.join(Image.splitlines()[:4])) \begin{tikzpicture}% [x={(-0.046385cm, 0.837431cm)}, y={(-0.243536cm, 0.519228cm)}, z={(0.968782cm, 0.170622cm)}, - sage: with open('polytope-tikz1.tex', 'w') as f: # not tested # optional - sage.rings.number_field + sage: with open('polytope-tikz1.tex', 'w') as f: # not tested ....: _ = f.write(Image) :: + sage: # needs sage.plot sage: Associahedron = Polyhedron(vertices=[[1, 0, 1], [1, 0, 0], [1, 1, 0], ....: [0, 0, -1], [0, 1, 0], [-1, 0, 0], ....: [0, 1, 1], [0, 0, 1], [0, -1, 0]]).polar() - sage: ImageAsso = Associahedron.projection().tikz([-15, -755, -655], 116, scale=1, # optional - sage.plot + sage: ImageAsso = Associahedron.projection().tikz([-15, -755, -655], 116, scale=1, ....: output_type='LatexExpr') - sage: print('\n'.join(ImageAsso.splitlines()[12:30])) # optional - sage.plot + sage: print('\n'.join(ImageAsso.splitlines()[12:30])) %% with the command: ._tikz_3d_in_3d and parameters: %% view = [-15, -755, -655] %% angle = 116 diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polygon.py b/src/sage/geometry/polyhedron/ppl_lattice_polygon.py index c7eac168fad..933275357d8 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polygon.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polygon.py @@ -407,11 +407,11 @@ def plot(self): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: P = LatticePolytope_PPL((1,0), (0,1), (0,0), (2,2)) - sage: P.plot() # optional - sage.plot + sage: P.plot() # needs sage.plot Graphics object consisting of 6 graphics primitives - sage: LatticePolytope_PPL([0], [1]).plot() # optional - sage.plot + sage: LatticePolytope_PPL([0], [1]).plot() # needs sage.plot Graphics object consisting of 3 graphics primitives - sage: LatticePolytope_PPL([0]).plot() # optional - sage.plot + sage: LatticePolytope_PPL([0]).plot() # needs sage.plot Graphics object consisting of 2 graphics primitives """ from sage.plot.point import point2d diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py index 6cd4cd457f0..91e4d4de82f 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py @@ -48,7 +48,7 @@ sage: square = LatticePolytope_PPL((-1,-1), (-1,1), (1,-1), (1,1)) sage: fibers = [ f.vertices() for f in square.fibration_generator(1) ]; fibers [((1, 0), (-1, 0)), ((0, 1), (0, -1)), ((-1, -1), (1, 1)), ((-1, 1), (1, -1))] - sage: square.pointsets_mod_automorphism(fibers) # optional - sage.groups + sage: square.pointsets_mod_automorphism(fibers) # needs sage.groups (frozenset({(-1, -1), (1, 1)}), frozenset({(-1, 0), (1, 0)})) AUTHORS: @@ -118,36 +118,36 @@ def LatticePolytope_PPL(*args): sage: LatticePolytope_PPL((0,0), (1,0), (0,1)) A 2-dimensional lattice polytope in ZZ^2 with 3 vertices - sage: from ppl import point, Generator_System, C_Polyhedron, Linear_Expression # optional - pplpy - sage: p = point(Linear_Expression([2,3],0)); p # optional - pplpy + sage: from ppl import point, Generator_System, C_Polyhedron, Linear_Expression # needs pplpy + sage: p = point(Linear_Expression([2,3],0)); p # needs pplpy point(2/1, 3/1) - sage: LatticePolytope_PPL(p) # optional - pplpy + sage: LatticePolytope_PPL(p) # needs pplpy A 0-dimensional lattice polytope in ZZ^2 with 1 vertex - sage: P = C_Polyhedron(Generator_System(p)); P # optional - pplpy + sage: P = C_Polyhedron(Generator_System(p)); P # needs pplpy A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point - sage: LatticePolytope_PPL(P) # optional - pplpy + sage: LatticePolytope_PPL(P) # needs pplpy A 0-dimensional lattice polytope in ZZ^2 with 1 vertex A ``TypeError`` is raised if the arguments do not specify a lattice polytope:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: LatticePolytope_PPL((0,0), (1/2,1)) # optional - pplpy + sage: LatticePolytope_PPL((0,0), (1/2,1)) # needs pplpy Traceback (most recent call last): ... TypeError: unable to convert rational 1/2 to an integer - sage: from ppl import point, Generator_System, C_Polyhedron, Linear_Expression # optional - pplpy - sage: p = point(Linear_Expression([2,3],0), 5); p # optional - pplpy + sage: from ppl import point, Generator_System, C_Polyhedron, Linear_Expression # needs pplpy + sage: p = point(Linear_Expression([2,3],0), 5); p # needs pplpy point(2/5, 3/5) - sage: LatticePolytope_PPL(p) # optional - pplpy + sage: LatticePolytope_PPL(p) # needs pplpy Traceback (most recent call last): ... TypeError: generator is not a lattice polytope generator - sage: P = C_Polyhedron(Generator_System(p)); P # optional - pplpy + sage: P = C_Polyhedron(Generator_System(p)); P # needs pplpy A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point - sage: LatticePolytope_PPL(P) # optional - pplpy + sage: LatticePolytope_PPL(P) # needs pplpy Traceback (most recent call last): ... TypeError: polyhedron has non-integral generators @@ -386,14 +386,14 @@ def integral_points(self): ....: (-1,2,-1), (-1,2,-2), (-1,1,-2), (-1,-1,2), (-1,-3,2)] sage: P = LatticePolytope_PPL(*v) sage: pts1 = P.integral_points() # Sage's own code - sage: pts2 = LatticePolytope(v).points() # optional - palp + sage: pts2 = LatticePolytope(v).points() # needs palp sage: for p in pts1: p.set_immutable() - sage: set(pts1) == set(pts2) # optional - palp + sage: set(pts1) == set(pts2) # needs palp True sage: len(Polyhedron(v).integral_points()) # takes about 1 ms 23 - sage: len(LatticePolytope(v).points()) # takes about 13 ms # optional - palp + sage: len(LatticePolytope(v).points()) # takes about 13 ms # needs palp 23 sage: len(LatticePolytope_PPL(*v).integral_points()) # takes about 0.5 ms 23 @@ -648,7 +648,7 @@ def pointsets_mod_automorphism(self, pointsets): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: square = LatticePolytope_PPL((-1,-1), (-1,1), (1,-1), (1,1)) sage: fibers = [f.vertices() for f in square.fibration_generator(1)] - sage: square.pointsets_mod_automorphism(fibers) # optional - sage.groups sage.graphs + sage: square.pointsets_mod_automorphism(fibers) # needs sage.graphs sage.groups (frozenset({(-1, -1), (1, 1)}), frozenset({(-1, 0), (1, 0)})) sage: cell24 = LatticePolytope_PPL( @@ -657,7 +657,7 @@ def pointsets_mod_automorphism(self, pointsets): ....: (1,-1,-1,0), (0,0,-1,0), (0,-1,0,0), (-1,0,0,0), (1,-1,0,0), (1,0,-1,0), ....: (0,1,1,-1), (-1,1,1,0), (-1,1,0,0), (-1,0,1,0), (0,-1,-1,1), (0,0,0,-1)) sage: fibers = [f.vertices() for f in cell24.fibration_generator(2)] - sage: cell24.pointsets_mod_automorphism(fibers) # long time # optional - sage.groups sage.graphs + sage: cell24.pointsets_mod_automorphism(fibers) # long time # needs sage.graphs sage.groups (frozenset({(-1, 0, 0, 0), (-1, 0, 0, 1), (0, 0, 0, -1), @@ -975,19 +975,20 @@ def restricted_automorphism_group(self, vertex_labels=None): EXAMPLES:: + sage: # needs sage.graphs sage.groups sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: Z3square = LatticePolytope_PPL((0,0), (1,2), (2,1), (3,3)) - sage: G1234 = Z3square.restricted_automorphism_group( # optional - sage.groups sage.graphs + sage: G1234 = Z3square.restricted_automorphism_group( ....: vertex_labels=(1,2,3,4)) - sage: G1234 == PermutationGroup([[(2,3)], [(1,2),(3,4)]]) # optional - sage.groups sage.graphs + sage: G1234 == PermutationGroup([[(2,3)], [(1,2),(3,4)]]) True - sage: G = Z3square.restricted_automorphism_group() # optional - sage.groups sage.graphs - sage: G == PermutationGroup([[((1,2),(2,1))], [((0,0),(1,2)), # optional - sage.groups sage.graphs + sage: G = Z3square.restricted_automorphism_group() + sage: G == PermutationGroup([[((1,2),(2,1))], [((0,0),(1,2)), ....: ((2,1),(3,3))], [((0,0),(3,3))]]) True - sage: set(G.domain()) == set(Z3square.vertices()) # optional - sage.groups sage.graphs + sage: set(G.domain()) == set(Z3square.vertices()) True - sage: (set(tuple(x) for x in G.orbit(Z3square.vertices()[0])) # optional - sage.groups sage.graphs + sage: (set(tuple(x) for x in G.orbit(Z3square.vertices()[0])) ....: == set([(0, 0), (1, 2), (3, 3), (2, 1)])) True sage: cell24 = LatticePolytope_PPL( @@ -995,7 +996,7 @@ def restricted_automorphism_group(self, vertex_labels=None): ....: (0,-1,0,1), (-1,0,0,1), (1,0,0,-1), (0,1,0,-1), (0,0,1,-1), (-1,1,1,-1), ....: (1,-1,-1,0), (0,0,-1,0), (0,-1,0,0), (-1,0,0,0), (1,-1,0,0), (1,0,-1,0), ....: (0,1,1,-1), (-1,1,1,0), (-1,1,0,0), (-1,0,1,0), (0,-1,-1,1), (0,0,0,-1)) - sage: cell24.restricted_automorphism_group().cardinality() # optional - sage.groups sage.graphs + sage: cell24.restricted_automorphism_group().cardinality() 1152 """ if not self.is_full_dimensional(): @@ -1048,25 +1049,25 @@ def lattice_automorphism_group(self, points=None, point_labels=None): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: Z3square = LatticePolytope_PPL((0,0), (1,2), (2,1), (3,3)) - sage: Z3square.lattice_automorphism_group() # optional - sage.groups sage.graphs + sage: Z3square.lattice_automorphism_group() # needs sage.graphs sage.groups Permutation Group with generators [(), ((1,2),(2,1)), ((0,0),(3,3)), ((0,0),(3,3))((1,2),(2,1))] - sage: G1 = Z3square.lattice_automorphism_group(point_labels=(1,2,3,4)) # optional - sage.groups sage.graphs - sage: G1 + sage: G1 = Z3square.lattice_automorphism_group(point_labels=(1,2,3,4)) # needs sage.graphs sage.groups + sage: G1 # needs sage.graphs sage.groups Permutation Group with generators [(), (2,3), (1,4), (1,4)(2,3)] - sage: G1.cardinality() # optional - sage.groups sage.graphs + sage: G1.cardinality() # needs sage.graphs sage.groups 4 - sage: G2 = Z3square.restricted_automorphism_group(vertex_labels=(1,2,3,4)) # optional - sage.groups sage.graphs - sage: G2 == PermutationGroup([[(2,3)], [(1,2),(3,4)], [(1,4)]]) # optional - sage.groups sage.graphs + sage: G2 = Z3square.restricted_automorphism_group(vertex_labels=(1,2,3,4)) # needs sage.graphs sage.groups + sage: G2 == PermutationGroup([[(2,3)], [(1,2),(3,4)], [(1,4)]]) # needs sage.graphs sage.groups True - sage: G2.cardinality() # optional - sage.groups sage.graphs + sage: G2.cardinality() # needs sage.graphs sage.groups 8 sage: points = Z3square.integral_points(); points ((0, 0), (1, 1), (1, 2), (2, 1), (2, 2), (3, 3)) - sage: Z3square.lattice_automorphism_group(points, # optional - sage.groups sage.graphs + sage: Z3square.lattice_automorphism_group(points, # needs sage.graphs sage.groups ....: point_labels=(1,2,3,4,5,6)) Permutation Group with generators [(), (3,4), (1,6)(2,5), (1,6)(2,5)(3,4)] @@ -1075,7 +1076,7 @@ def lattice_automorphism_group(self, points=None, point_labels=None): sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL sage: lp = LatticePolytope_PPL((1,0,0), (0,1,0), (-1,-1,0)) - sage: lp.lattice_automorphism_group(point_labels=(0,1,2)) # optional - sage.groups sage.graphs + sage: lp.lattice_automorphism_group(point_labels=(0,1,2)) # needs sage.graphs sage.groups Permutation Group with generators [(), (1,2), (0,1), (0,1,2), (0,2,1), (0,2)] """ if not self.is_full_dimensional(): diff --git a/src/sage/geometry/polyhedron/representation.py b/src/sage/geometry/polyhedron/representation.py index bab34f3481d..554e36ec239 100644 --- a/src/sage/geometry/polyhedron/representation.py +++ b/src/sage/geometry/polyhedron/representation.py @@ -799,8 +799,8 @@ def is_facet_defining_inequality(self, other): sage: Q = Polyhedron(ieqs=[[0,2,0,3]]) sage: Q.inequalities()[0].is_facet_defining_inequality(P) True - sage: Q = Polyhedron(ieqs=[[0,AA(2).sqrt(),0,3]]) # optional - sage.rings.number_field - sage: Q.inequalities()[0].is_facet_defining_inequality(P) # optional - sage.rings.number_field + sage: Q = Polyhedron(ieqs=[[0,AA(2).sqrt(),0,3]]) # needs sage.rings.number_field + sage: Q.inequalities()[0].is_facet_defining_inequality(P) True sage: Q = Polyhedron(ieqs=[[1,1,0,0]]) sage: Q.inequalities()[0].is_facet_defining_inequality(P) @@ -902,9 +902,9 @@ def _repr_(self): Test that :trac:`21105` has been fixed:: sage: x = polygen(ZZ, 'x') - sage: K. = NumberField(x^3 - 2, 'a', embedding=1.26) # optional - sage.rings.number_field - sage: P = Polyhedron(vertices=[(1,1,cbrt2),(cbrt2,1,1)]) # optional - sage.rings.number_field - sage: P.inequalities() # optional - sage.rings.number_field + sage: K. = NumberField(x^3 - 2, 'a', embedding=1.26) # needs sage.rings.number_field + sage: P = Polyhedron(vertices=[(1,1,cbrt2),(cbrt2,1,1)]) # needs sage.rings.number_field + sage: P.inequalities() # needs sage.rings.number_field (An inequality (-cbrt2^2 - cbrt2 - 1, 0, 0) x + cbrt2^2 + cbrt2 + 2 >= 0, An inequality (cbrt2^2 + cbrt2 + 1, 0, 0) x - cbrt2^2 + cbrt2 + 1 >= 0) """ @@ -994,7 +994,7 @@ def outer_normal(self): EXAMPLES:: - sage: p = Polyhedron(vertices = [[0,0,0],[1,1,0],[1,2,0]]) + sage: p = Polyhedron(vertices=[[0,0,0],[1,1,0],[1,2,0]]) sage: a = next(p.inequality_generator()) sage: a.outer_normal() (1, -1, 0) diff --git a/src/sage/geometry/pseudolines.py b/src/sage/geometry/pseudolines.py index 4bb8d6ac8c9..8ce4496c65a 100644 --- a/src/sage/geometry/pseudolines.py +++ b/src/sage/geometry/pseudolines.py @@ -49,7 +49,7 @@ sage: p = PseudolineArrangement(permutations) sage: p Arrangement of pseudolines of size 4 - sage: p.show() # optional - sage.plot + sage: p.show() # needs sage.plot **Sequence of transpositions** @@ -67,7 +67,7 @@ sage: p = PseudolineArrangement(transpositions) sage: p Arrangement of pseudolines of size 4 - sage: p.show() # optional - sage.plot + sage: p.show() # needs sage.plot Note that this ordering is not necessarily unique. @@ -129,9 +129,9 @@ avoid a common crossing of three lines by adding a random noise to `b`:: sage: n = 20 - sage: l = sorted(zip(Subsets(20*n, n).random_element(), # optional - sage.combinat + sage: l = sorted(zip(Subsets(20*n, n).random_element(), ....: [randint(0, 20*n) + random() for i in range(n)])) - sage: print(l[:5]) # not tested # optional - sage.combinat + sage: print(l[:5]) # not tested # needs sage.combinat [(96, 278.0130613051349), (74, 332.92512282478714), (13, 155.65820951249867), (209, 34.753946221755307), (147, 193.51376457741441)] @@ -140,16 +140,16 @@ sage: permutations = [[0..i-1] + [i+1..n-1] for i in range(n)] sage: def a(x): return l[x][0] sage: def b(x): return l[x][1] - sage: for i, perm in enumerate(permutations): # optional - sage.combinat + sage: for i, perm in enumerate(permutations): ....: perm.sort(key=lambda j: (b(j)-b(i))/(a(i)-a(j))) And finally build the line arrangement:: sage: from sage.geometry.pseudolines import PseudolineArrangement - sage: p = PseudolineArrangement(permutations) # optional - sage.combinat - sage: print(p) # optional - sage.combinat + sage: p = PseudolineArrangement(permutations) + sage: print(p) Arrangement of pseudolines of size 20 - sage: p.show(figsize=[20,8]) # optional - sage.combinat sage.plot + sage: p.show(figsize=[20,8]) # needs sage.combinat sage.plot Author ^^^^^^ @@ -419,14 +419,14 @@ def show(self, **args): sage: from sage.geometry.pseudolines import PseudolineArrangement sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 1, 0], [2, 1, 0]] sage: p = PseudolineArrangement(permutations) - sage: p.show(figsize=[7,5]) # optional - sage.plot + sage: p.show(figsize=[7,5]) # needs sage.plot TESTS:: sage: from sage.geometry.pseudolines import PseudolineArrangement sage: permutations = [[3, 2, 1], [3, 2, 0], [3, 0, 1], [2, 0, 1]] sage: p = PseudolineArrangement(permutations) - sage: p.show() # optional - sage.plot + sage: p.show() # needs sage.plot Traceback (most recent call last): ... ValueError: There has been a problem while plotting the figure... diff --git a/src/sage/geometry/relative_interior.py b/src/sage/geometry/relative_interior.py index d9ba65bbff5..b57db6bd260 100644 --- a/src/sage/geometry/relative_interior.py +++ b/src/sage/geometry/relative_interior.py @@ -324,11 +324,11 @@ def __eq__(self, other): sage: ri_segment = segment.relative_interior(); ri_segment Relative interior of a 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices - sage: segment2 = Polyhedron([[1, 2], [3, 4]], base_ring=AA) # optional - sage.rings.number_field - sage: ri_segment2 = segment2.relative_interior(); ri_segment2 # optional - sage.rings.number_field + sage: segment2 = Polyhedron([[1, 2], [3, 4]], base_ring=AA) # needs sage.rings.number_field + sage: ri_segment2 = segment2.relative_interior(); ri_segment2 # needs sage.rings.number_field Relative interior of a 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices - sage: ri_segment == ri_segment2 # optional - sage.rings.number_field + sage: ri_segment == ri_segment2 # needs sage.rings.number_field True TESTS:: @@ -355,11 +355,11 @@ def __ne__(self, other): sage: ri_segment = segment.relative_interior(); ri_segment Relative interior of a 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices - sage: segment2 = Polyhedron([[1, 2], [3, 4]], base_ring=AA) # optional - sage.rings.number_field - sage: ri_segment2 = segment2.relative_interior(); ri_segment2 # optional - sage.rings.number_field + sage: segment2 = Polyhedron([[1, 2], [3, 4]], base_ring=AA) # needs sage.rings.number_field + sage: ri_segment2 = segment2.relative_interior(); ri_segment2 # needs sage.rings.number_field Relative interior of a 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices - sage: ri_segment != ri_segment2 # optional - sage.rings.number_field + sage: ri_segment != ri_segment2 # needs sage.rings.number_field False """ return not (self == other) diff --git a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py index 0253cdc1888..c0161ab0c4f 100644 --- a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py +++ b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py @@ -99,7 +99,7 @@ class ParametrizedSurface3D(SageObject): sage: ellipsoid = ParametrizedSurface3D(ellipsoid_eq, coords, 'ellipsoid'); ellipsoid Parametrized surface ('ellipsoid') with equation (cos(u1)*cos(u2), 2*cos(u2)*sin(u1), 3*sin(u2)) - sage: ellipsoid.plot() # optional - sage.plot + sage: ellipsoid.plot() # needs sage.plot Graphics3d Object Standard surfaces can be constructed using the ``surfaces`` generator:: @@ -127,7 +127,7 @@ class ParametrizedSurface3D(SageObject): sage: enneper = surfaces.Enneper(); enneper Parametrized surface ('Enneper's surface') with equation (-1/9*(u^2 - 3*v^2 - 3)*u, -1/9*(3*u^2 - v^2 + 3)*v, 1/3*u^2 - 1/3*v^2) - sage: enneper.plot(aspect_ratio='automatic') # optional - sage.plot + sage: enneper.plot(aspect_ratio='automatic') # needs sage.plot Graphics3d Object We construct an ellipsoid whose axes are given by symbolic variables `a`, @@ -255,6 +255,7 @@ class ParametrizedSurface3D(SageObject): We can easily generate a color plot of the Gaussian curvature of a surface. Here we deal with the ellipsoid:: + sage: # needs numpy sage: u1, u2 = var('u1,u2', domain='real') sage: u = [u1,u2] sage: ellipsoid_equation(u1,u2) = [2*cos(u1)*cos(u2),1.5*cos(u1)*sin(u2),sin(u1)] @@ -264,27 +265,27 @@ class ParametrizedSurface3D(SageObject): sage: u2min, u2max = 0, 6.28 sage: u1num, u2num = 10, 20 sage: # make the arguments array - sage: from numpy import linspace # optional - numpy - sage: u1_array = linspace(u1min, u1max, u1num) # optional - numpy - sage: u2_array = linspace(u2min, u2max, u2num) # optional - numpy - sage: u_array = [(uu1,uu2) for uu1 in u1_array for uu2 in u2_array] # optional - numpy + sage: from numpy import linspace + sage: u1_array = linspace(u1min, u1max, u1num) + sage: u2_array = linspace(u2min, u2max, u2num) + sage: u_array = [(uu1,uu2) for uu1 in u1_array for uu2 in u2_array] sage: # Find the gaussian curvature - sage: K(u1,u2) = ellipsoid.gauss_curvature() # optional - numpy - sage: # Make array of K values # optional - numpy - sage: K_array = [K(uu[0],uu[1]) for uu in u_array] # optional - numpy + sage: K(u1,u2) = ellipsoid.gauss_curvature() + sage: # Make array of K values + sage: K_array = [K(uu[0],uu[1]) for uu in u_array] sage: # Find minimum and max of the Gauss curvature - sage: K_max = max(K_array) # optional - numpy - sage: K_min = min(K_array) # optional - numpy + sage: K_max = max(K_array) + sage: K_min = min(K_array) sage: # Make the array of color coefficients - sage: cc_array = [(ccc - K_min)/(K_max - K_min) for ccc in K_array] # optional - numpy - sage: points_array = [ellipsoid_equation(u_array[counter][0], # optional - numpy + sage: cc_array = [(ccc - K_min)/(K_max - K_min) for ccc in K_array] + sage: points_array = [ellipsoid_equation(u_array[counter][0], ....: u_array[counter][1]) ....: for counter in range(0,len(u_array))] - sage: curvature_ellipsoid_plot = sum(point([xx # optional - numpy sage.plot + sage: curvature_ellipsoid_plot = sum(point([xx # needs sage.plot ....: for xx in points_array[counter]], ....: color=hue(cc_array[counter]/2)) ....: for counter in range(0,len(u_array))) - sage: curvature_ellipsoid_plot.show(aspect_ratio=1) # optional - numpy sage.plot + sage: curvature_ellipsoid_plot.show(aspect_ratio=1) # needs sage.plot We can find the principal curvatures and principal directions of the elliptic paraboloid:: @@ -341,7 +342,7 @@ class ParametrizedSurface3D(SageObject): sage: g3 = [c[-1] for c in S.geodesics_numerical((0,0), ....: (cos(2*pi/3),sin(2*pi/3)), ....: (0,2*pi,100))] - sage: (S.plot(opacity=0.3) + line3d(g1, color='red') # optional - sage.plot + sage: (S.plot(opacity=0.3) + line3d(g1, color='red') # needs sage.plot ....: + line3d(g2, color='red') + line3d(g3, color='red')).show() """ @@ -514,7 +515,7 @@ def plot(self, urange=None, vrange=None, **kwds): sage: u, v = var('u, v', domain='real') sage: eq = (3*u + 3*u*v^2 - u^3, 3*v + 3*u^2*v - v^3, 3*(u^2-v^2)) sage: enneper = ParametrizedSurface3D(eq, (u, v), 'Enneper Surface') - sage: enneper.plot((-5, 5), (-5, 5)) # optional - sage.plot + sage: enneper.plot((-5, 5), (-5, 5)) # needs sage.plot Graphics3d Object """ diff --git a/src/sage/geometry/riemannian_manifolds/surface3d_generators.py b/src/sage/geometry/riemannian_manifolds/surface3d_generators.py index 3619c6c2952..ba8eff2ed2a 100644 --- a/src/sage/geometry/riemannian_manifolds/surface3d_generators.py +++ b/src/sage/geometry/riemannian_manifolds/surface3d_generators.py @@ -53,7 +53,7 @@ def Catenoid(c=1, name="Catenoid"): sage: cat = surfaces.Catenoid(); cat Parametrized surface ('Catenoid') with equation (cos(u)*cosh(v), cosh(v)*sin(u), v) - sage: cat.plot() # optional - sage.plot + sage: cat.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -86,7 +86,7 @@ def Crosscap(r=1, name="Crosscap"): sage: crosscap = surfaces.Crosscap(); crosscap Parametrized surface ('Crosscap') with equation ((cos(v) + 1)*cos(u), (cos(v) + 1)*sin(u), -sin(v)*tanh(-pi + u)) - sage: crosscap.plot() # optional - sage.plot + sage: crosscap.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -120,7 +120,7 @@ def Dini(a=1, b=1, name="Dini's surface"): sage: dini = surfaces.Dini(a=3, b=4); dini Parametrized surface ('Dini's surface') with equation (3*cos(u)*sin(v), 3*sin(u)*sin(v), 4*u + 3*cos(v) + 3*log(tan(1/2*v))) - sage: dini.plot() # optional - sage.plot + sage: dini.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -158,7 +158,7 @@ def Ellipsoid(center=(0, 0, 0), axes=(1, 1, 1), name="Ellipsoid"): sage: ell = surfaces.Ellipsoid(axes=(1, 2, 3)); ell Parametrized surface ('Ellipsoid') with equation (cos(u)*cos(v), 2*cos(v)*sin(u), 3*sin(v)) - sage: ell.plot() # optional - sage.plot + sage: ell.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -193,7 +193,7 @@ def Enneper(name="Enneper's surface"): sage: enn = surfaces.Enneper(); enn Parametrized surface ('Enneper's surface') with equation (-1/9*(u^2 - 3*v^2 - 3)*u, -1/9*(3*u^2 - v^2 + 3)*v, 1/3*u^2 - 1/3*v^2) - sage: enn.plot() # optional - sage.plot + sage: enn.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -227,7 +227,7 @@ def Helicoid(h=1, name="Helicoid"): sage: helicoid = surfaces.Helicoid(h=2); helicoid Parametrized surface ('Helicoid') with equation (rho*cos(theta), rho*sin(theta), theta/pi) - sage: helicoid.plot() # optional - sage.plot + sage: helicoid.plot() # needs sage.plot Graphics3d Object """ rho, theta = var('rho, theta') @@ -260,7 +260,7 @@ def Klein(r=1, name="Klein bottle"): sage: klein = surfaces.Klein(); klein Parametrized surface ('Klein bottle') with equation (-(sin(1/2*u)*sin(2*v) - cos(1/2*u)*sin(v) - 1)*cos(u), -(sin(1/2*u)*sin(2*v) - cos(1/2*u)*sin(v) - 1)*sin(u), cos(1/2*u)*sin(2*v) + sin(1/2*u)*sin(v)) - sage: klein.plot() # optional - sage.plot + sage: klein.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -291,7 +291,7 @@ def MonkeySaddle(name="Monkey saddle"): sage: saddle = surfaces.MonkeySaddle(); saddle Parametrized surface ('Monkey saddle') with equation (u, v, u^3 - 3*u*v^2) - sage: saddle.plot() # optional - sage.plot + sage: saddle.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -327,12 +327,12 @@ def Paraboloid(a=1, b=1, c=1, elliptic=True, name=None): sage: epar = surfaces.Paraboloid(1, 3, 2); epar Parametrized surface ('Elliptic paraboloid') with equation (u, v, 2*u^2 + 2/9*v^2) - sage: epar.plot() # optional - sage.plot + sage: epar.plot() # needs sage.plot Graphics3d Object sage: hpar = surfaces.Paraboloid(2, 3, 1, elliptic=False); hpar Parametrized surface ('Hyperbolic paraboloid') with equation (u, v, -1/4*u^2 + 1/9*v^2) - sage: hpar.plot() # optional - sage.plot + sage: hpar.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -372,7 +372,7 @@ def Sphere(center=(0, 0, 0), R=1, name="Sphere"): sage: sphere = surfaces.Sphere(center=(0, 1, -1), R=2); sphere Parametrized surface ('Sphere') with equation (2*cos(u)*cos(v), 2*cos(v)*sin(u) + 1, 2*sin(v) - 1) - sage: sphere.plot() # optional - sage.plot + sage: sphere.plot() # needs sage.plot Graphics3d Object Note that the radius of the sphere can be negative. The surface thus @@ -382,14 +382,14 @@ def Sphere(center=(0, 0, 0), R=1, name="Sphere"): sage: octant1 = surfaces.Sphere(R=1); octant1 Parametrized surface ('Sphere') with equation (cos(u)*cos(v), cos(v)*sin(u), sin(v)) - sage: octant1.plot((0, pi/2), (0, pi/2)) # optional - sage.plot + sage: octant1.plot((0, pi/2), (0, pi/2)) # needs sage.plot Graphics3d Object with the first octant of the unit sphere with negative radius:: sage: octant2 = surfaces.Sphere(R=-1); octant2 Parametrized surface ('Sphere') with equation (-cos(u)*cos(v), -cos(v)*sin(u), -sin(v)) - sage: octant2.plot((0, pi/2), (0, pi/2)) # optional - sage.plot + sage: octant2.plot((0, pi/2), (0, pi/2)) # needs sage.plot Graphics3d Object """ return SurfaceGenerators.Ellipsoid(center, (R, R, R), name) @@ -421,7 +421,7 @@ def Torus(r=2, R=3, name="Torus"): sage: torus = surfaces.Torus(); torus Parametrized surface ('Torus') with equation ((2*cos(v) + 3)*cos(u), (2*cos(v) + 3)*sin(u), 2*sin(v)) - sage: torus.plot() # optional - sage.plot + sage: torus.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') @@ -448,7 +448,7 @@ def WhitneyUmbrella(name="Whitney's umbrella"): sage: whitney = surfaces.WhitneyUmbrella(); whitney Parametrized surface ('Whitney's umbrella') with equation (u*v, u, v^2) - sage: whitney.plot() # optional - sage.plot + sage: whitney.plot() # needs sage.plot Graphics3d Object """ u, v = var('u, v') diff --git a/src/sage/geometry/toric_lattice.py b/src/sage/geometry/toric_lattice.py index a8a2ad38ba6..fab14e4e7af 100644 --- a/src/sage/geometry/toric_lattice.py +++ b/src/sage/geometry/toric_lattice.py @@ -1068,7 +1068,7 @@ def plot(self, **options): EXAMPLES:: sage: N = ToricLattice(3) - sage: N.plot() # optional - sage.plot + sage: N.plot() # needs sage.plot Graphics3d Object """ if "show_lattice" not in options: @@ -1215,12 +1215,12 @@ def plot(self, **options): sage: N = ToricLattice(3) sage: sublattice = N.submodule_with_basis([(1,1,0), (3,2,1)]) - sage: sublattice.plot() # optional - sage.plot + sage: sublattice.plot() # needs sage.plot Graphics3d Object Now we plot both the ambient lattice and its sublattice:: - sage: N.plot() + sublattice.plot(point_color="red") # optional - sage.plot + sage: N.plot() + sublattice.plot(point_color="red") # needs sage.plot Graphics3d Object """ if "show_lattice" not in options: diff --git a/src/sage/geometry/toric_lattice_element.pyx b/src/sage/geometry/toric_lattice_element.pyx index 6c6d28800b9..40897c019f5 100644 --- a/src/sage/geometry/toric_lattice_element.pyx +++ b/src/sage/geometry/toric_lattice_element.pyx @@ -394,7 +394,7 @@ cdef class ToricLatticeElement(Vector_integer_dense): sage: N = ToricLattice(3) sage: n = N(1,2,3) - sage: n.plot() # optional - sage.plot + sage: n.plot() # needs sage.plot Graphics3d Object """ tp = ToricPlotter(options, self.parent().degree()) diff --git a/src/sage/geometry/toric_plotter.py b/src/sage/geometry/toric_plotter.py index 9a14918a2ab..50b4008eb0f 100644 --- a/src/sage/geometry/toric_plotter.py +++ b/src/sage/geometry/toric_plotter.py @@ -14,8 +14,8 @@ In most cases, this module is used indirectly, e.g. :: - sage: fan = toric_varieties.dP6().fan() # optional - palp - sage: fan.plot() # optional - palp sage.plot + sage: fan = toric_varieties.dP6().fan() # needs palp sage.graphs + sage: fan.plot() # needs palp sage.graphs sage.plot Graphics object consisting of 31 graphics primitives You may change default plotting options as follows:: @@ -25,12 +25,12 @@ sage: toric_plotter.options(show_rays=False) sage: toric_plotter.options("show_rays") False - sage: fan.plot() # optional - palp sage.plot + sage: fan.plot() # needs palp sage.graphs sage.plot Graphics object consisting of 19 graphics primitives sage: toric_plotter.reset_options() sage: toric_plotter.options("show_rays") True - sage: fan.plot() # optional - palp sage.plot + sage: fan.plot() # needs palp sage.graphs sage.plot Graphics object consisting of 31 graphics primitives """ @@ -134,10 +134,10 @@ class ToricPlotter(SageObject): directly. Instead, use plotting method of the object which you want to plot, e.g. :: - sage: fan = toric_varieties.dP6().fan() # optional - palp - sage: fan.plot() # optional - palp sage.plot + sage: fan = toric_varieties.dP6().fan() # needs palp sage.graphs + sage: fan.plot() # needs palp sage.graphs sage.plot Graphics object consisting of 31 graphics primitives - sage: print(fan.plot()) # optional - palp sage.plot + sage: print(fan.plot()) # needs palp sage.graphs sage.plot Graphics object consisting of 31 graphics primitives If you do want to create your own plotting function for some toric @@ -163,24 +163,25 @@ class ToricPlotter(SageObject): For example, the plot from the previous example can be obtained as follows:: + sage: # needs palp sage.graphs sage.plot sage: from sage.geometry.toric_plotter import ToricPlotter sage: options = dict() # use default for everything - sage: tp = ToricPlotter(options, fan.lattice().degree()) # optional - palp - sage: tp.include_points(fan.rays()) # optional - palp - sage: tp.adjust_options() # optional - palp - sage: tp.set_rays(fan.rays()) # optional - palp - sage: result = tp.plot_lattice() # optional - palp sage.plot - sage: result += tp.plot_rays() # optional - palp sage.plot - sage: result += tp.plot_generators() # optional - palp sage.plot - sage: result += tp.plot_walls(fan(2)) # optional - palp sage.plot - sage: result # optional - palp sage.plot + sage: tp = ToricPlotter(options, fan.lattice().degree()) + sage: tp.include_points(fan.rays()) + sage: tp.adjust_options() + sage: tp.set_rays(fan.rays()) + sage: result = tp.plot_lattice() + sage: result += tp.plot_rays() + sage: result += tp.plot_generators() + sage: result += tp.plot_walls(fan(2)) + sage: result Graphics object consisting of 31 graphics primitives In most situations it is only necessary to include generators of rays, in this case they can be passed to the constructor as an optional argument. In the example above, the toric plotter can be completely set up using :: - sage: tp = ToricPlotter(options, fan.lattice().degree(), fan.rays()) # optional - palp + sage: tp = ToricPlotter(options, fan.lattice().degree(), fan.rays()) # needs palp sage.graphs sage.plot All options are exposed as attributes of toric plotters and can be modified after constructions, however you will have to manually call @@ -389,7 +390,7 @@ def plot_generators(self): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2, [(3,4)]) - sage: tp.plot_generators() # optional - sage.plot + sage: tp.plot_generators() # needs sage.plot Graphics object consisting of 1 graphics primitive """ generators = self.generators @@ -440,7 +441,7 @@ def plot_labels(self, labels, positions): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2) - sage: tp.plot_labels("u", [(1.5,0)]) # optional - sage.plot + sage: tp.plot_labels("u", [(1.5,0)]) # needs sage.plot Graphics object consisting of 1 graphics primitive """ result = Graphics() @@ -474,7 +475,7 @@ def plot_lattice(self): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2) sage: tp.adjust_options() - sage: tp.plot_lattice() # optional - sage.plot + sage: tp.plot_lattice() # needs sage.plot Graphics object consisting of 1 graphics primitive """ if not self.show_lattice: @@ -518,7 +519,7 @@ def plot_points(self, points): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2) sage: tp.adjust_options() - sage: tp.plot_points([(1,0), (0,1)]) # optional - sage.plot + sage: tp.plot_points([(1,0), (0,1)]) # needs sage.plot Graphics object consisting of 1 graphics primitive """ return point(points, color=self.point_color, size=self.point_size, @@ -542,7 +543,7 @@ def plot_ray_labels(self): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2, [(3,4)]) - sage: tp.plot_ray_labels() # optional - sage.plot + sage: tp.plot_ray_labels() # needs sage.plot Graphics object consisting of 1 graphics primitive """ return self.plot_labels(self.ray_label, @@ -563,7 +564,7 @@ def plot_rays(self): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2, [(3,4)]) - sage: tp.plot_rays() # optional - sage.plot + sage: tp.plot_rays() # needs sage.plot Graphics object consisting of 2 graphics primitives """ result = Graphics() @@ -605,14 +606,14 @@ def plot_walls(self, walls): sage: quadrant = Cone([(1,0), (0,1)]) sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2, quadrant.rays()) - sage: tp.plot_walls([quadrant]) # optional - sage.plot + sage: tp.plot_walls([quadrant]) # needs sage.plot Graphics object consisting of 2 graphics primitives Let's also check that the truncating polyhedron is functioning correctly:: sage: tp = ToricPlotter({"mode": "box"}, 2, quadrant.rays()) - sage: tp.plot_walls([quadrant]) # optional - sage.plot + sage: tp.plot_walls([quadrant]) # needs sage.plot Graphics object consisting of 2 graphics primitives """ result = Graphics() @@ -702,12 +703,12 @@ def set_rays(self, generators): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2) sage: tp.adjust_options() - sage: tp.plot_rays() # optional - sage.plot + sage: tp.plot_rays() # needs sage.plot Traceback (most recent call last): ... AttributeError: 'ToricPlotter' object has no attribute 'rays' sage: tp.set_rays([(0,1)]) - sage: tp.plot_rays() # optional - sage.plot + sage: tp.plot_rays() # needs sage.plot Graphics object consisting of 2 graphics primitives """ d = self.dimension @@ -781,21 +782,22 @@ def color_list(color, n): EXAMPLES:: + sage: # needs sage.plot sage: from sage.geometry.toric_plotter import color_list - sage: color_list("grey", 1) # optional - sage.plot + sage: color_list("grey", 1) [RGB color (0.5019607843137255, 0.5019607843137255, 0.5019607843137255)] - sage: len(color_list("grey", 3)) # optional - sage.plot + sage: len(color_list("grey", 3)) 3 - sage: L = color_list("rainbow", 3) # optional - sage.plot - sage: L # optional - sage.plot + sage: L = color_list("rainbow", 3) + sage: L [RGB color (1.0, 0.0, 0.0), RGB color (0.0, 1.0, 0.0), RGB color (0.0, 0.0, 1.0)] - sage: color_list(L, 3) # optional - sage.plot + sage: color_list(L, 3) [RGB color (1.0, 0.0, 0.0), RGB color (0.0, 1.0, 0.0), RGB color (0.0, 0.0, 1.0)] - sage: color_list(L, 4) # optional - sage.plot + sage: color_list(L, 4) Traceback (most recent call last): ... ValueError: expected 4 colors, got 3! @@ -1106,9 +1108,9 @@ def sector(ray1, ray2, **extra_options): EXAMPLES:: sage: from sage.geometry.toric_plotter import sector - sage: sector((1,0), (0,1)) + sage: sector((1,0), (0,1)) # needs sage.symbolic Graphics object consisting of 1 graphics primitive - sage: sector((3,2,1), (1,2,3)) + sage: sector((3,2,1), (1,2,3)) # needs sage.plot Graphics3d Object """ ray1 = vector(RDF, ray1) diff --git a/src/sage/geometry/triangulation/element.py b/src/sage/geometry/triangulation/element.py index 793b383f9dc..7486488adb1 100644 --- a/src/sage/geometry/triangulation/element.py +++ b/src/sage/geometry/triangulation/element.py @@ -23,7 +23,7 @@ sage: points = PointConfiguration(p) sage: triang = points.triangulate(); triang (<0,1,2,5>, <0,1,3,5>, <1,3,4,5>) - sage: triang.plot(axes=False) # optional - sage.plot + sage: triang.plot(axes=False) # needs sage.plot Graphics3d Object See :mod:`sage.geometry.triangulation.point_configuration` for more details. @@ -68,7 +68,7 @@ def triangulation_render_2d(triangulation, **kwds): sage: points = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) sage: triang = points.triangulate() - sage: triang.plot(axes=False, aspect_ratio=1) # indirect doctest # optional - sage.plot + sage: triang.plot(axes=False, aspect_ratio=1) # indirect doctest # needs sage.plot Graphics object consisting of 12 graphics primitives """ from sage.plot.all import point2d, line2d, polygon2d @@ -130,7 +130,7 @@ def triangulation_render_3d(triangulation, **kwds): sage: p = [[0,-1,-1],[0,0,1],[0,1,0], [1,-1,-1],[1,0,1],[1,1,0]] sage: points = PointConfiguration(p) sage: triang = points.triangulate() - sage: triang.plot(axes=False) # indirect doctest # optional - sage.plot + sage: triang.plot(axes=False) # indirect doctest # needs sage.plot Graphics3d Object """ from sage.plot.plot3d.all import point3d, line3d, polygon3d @@ -407,7 +407,7 @@ def plot(self, **kwds): sage: triangulation = p.triangulate() sage: triangulation (<1,3,4>, <2,3,4>) - sage: triangulation.plot(axes=False) # optional - sage.plot + sage: triangulation.plot(axes=False) # needs sage.plot Graphics object consisting of 12 graphics primitives """ dim = self.point_configuration().dim() @@ -524,7 +524,7 @@ def fan(self, origin=None): sage: triangulation = pc.triangulate() sage: fan = triangulation.fan(); fan Rational polyhedral fan in 2-d lattice N - sage: fan.is_equivalent(toric_varieties.P2().fan()) # optional - palp + sage: fan.is_equivalent(toric_varieties.P2().fan()) # needs palp sage.graphs True Toric diagrams (the `\ZZ_5` hyperconifold):: @@ -567,12 +567,12 @@ def simplicial_complex(self): EXAMPLES:: sage: p = polytopes.cuboctahedron() - sage: sc = p.triangulate(engine='internal').simplicial_complex(); sc # optional - sage.graphs + sage: sc = p.triangulate(engine='internal').simplicial_complex(); sc # needs sage.graphs Simplicial complex with 12 vertices and 16 facets Any convex set is contractable, so its reduced homology groups vanish:: - sage: sc.homology() # optional - sage.graphs + sage: sc.homology() # needs sage.graphs {0: 0, 1: 0, 2: 0, 3: 0} """ from sage.topology.simplicial_complex import SimplicialComplex @@ -670,19 +670,19 @@ def boundary_simplicial_complex(self): sage: p = polytopes.cuboctahedron() sage: triangulation = p.triangulate(engine='internal') - sage: bd_sc = triangulation.boundary_simplicial_complex(); bd_sc # optional - sage.graphs + sage: bd_sc = triangulation.boundary_simplicial_complex(); bd_sc # needs sage.graphs Simplicial complex with 12 vertices and 20 facets The boundary of every convex set is a topological sphere, so it has spherical homology:: - sage: bd_sc.homology() # optional - sage.graphs + sage: bd_sc.homology() # needs sage.graphs {0: 0, 1: 0, 2: Z} It is a subcomplex of ``self`` as a :meth:`simplicial_complex`:: - sage: sc = triangulation.simplicial_complex() # optional - sage.graphs - sage: all(f in sc for f in bd_sc.maximal_faces()) # optional - sage.graphs + sage: sc = triangulation.simplicial_complex() # needs sage.graphs + sage: all(f in sc for f in bd_sc.maximal_faces()) # needs sage.graphs True """ from sage.topology.simplicial_complex import SimplicialComplex @@ -739,9 +739,9 @@ def polyhedral_complex(self, **kwds): sage: pc = PointConfiguration(P.vertices()) sage: T = pc.placing_triangulation(); T (<0,1,2,7>, <0,1,5,7>, <0,2,3,7>, <0,3,4,7>, <0,4,5,7>, <1,5,6,7>) - sage: C = T.polyhedral_complex(); C # optional - sage.graphs + sage: C = T.polyhedral_complex(); C # needs sage.graphs Polyhedral complex with 6 maximal cells - sage: [P.vertices_list() for P in C.maximal_cells_sorted()] # optional - sage.graphs + sage: [P.vertices_list() for P in C.maximal_cells_sorted()] # needs sage.graphs [[[-1, -1, -1], [-1, -1, 1], [-1, 1, 1], [1, -1, -1]], [[-1, -1, -1], [-1, 1, -1], [-1, 1, 1], [1, 1, -1]], [[-1, -1, -1], [-1, 1, 1], [1, -1, -1], [1, 1, -1]], @@ -775,9 +775,9 @@ def boundary_polyhedral_complex(self, **kwds): sage: pc = PointConfiguration(P.vertices()) sage: T = pc.placing_triangulation(); T (<0,1,2,7>, <0,1,5,7>, <0,2,3,7>, <0,3,4,7>, <0,4,5,7>, <1,5,6,7>) - sage: bd_C = T.boundary_polyhedral_complex(); bd_C # optional - sage.graphs + sage: bd_C = T.boundary_polyhedral_complex(); bd_C # needs sage.graphs Polyhedral complex with 12 maximal cells - sage: [P.vertices_list() for P in bd_C.maximal_cells_sorted()] # optional - sage.graphs + sage: [P.vertices_list() for P in bd_C.maximal_cells_sorted()] # needs sage.graphs [[[-1, -1, -1], [-1, -1, 1], [-1, 1, 1]], [[-1, -1, -1], [-1, -1, 1], [1, -1, -1]], [[-1, -1, -1], [-1, 1, -1], [-1, 1, 1]], @@ -793,8 +793,8 @@ def boundary_polyhedral_complex(self, **kwds): It is a subcomplex of ``self`` as a :meth:`polyhedral_complex`:: - sage: C = T.polyhedral_complex() # optional - sage.graphs - sage: bd_C.is_subcomplex(C) # optional - sage.graphs + sage: C = T.polyhedral_complex() # needs sage.graphs + sage: bd_C.is_subcomplex(C) # needs sage.graphs True """ from sage.geometry.polyhedral_complex import PolyhedralComplex @@ -918,7 +918,7 @@ def adjacency_graph(self): sage: p = PointConfiguration([[1,0,0], [0,1,0], [0,0,1], [-1,0,1], ....: [1,0,-1], [-1,0,0], [0,-1,0], [0,0,-1]]) sage: t = p.triangulate() - sage: t.adjacency_graph() # optional - sage.graphs + sage: t.adjacency_graph() # needs sage.graphs Graph on 8 vertices """ diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index 4f1bbde16d7..d75af2af4ce 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -65,7 +65,7 @@ (2, 3, 4) sage: list(t) [(1, 3, 4), (2, 3, 4)] - sage: t.plot(axes=False) # optional - sage.plot + sage: t.plot(axes=False) # needs sage.plot Graphics object consisting of 12 graphics primitives .. PLOT:: @@ -95,7 +95,7 @@ sage: p = [[0,-1,-1], [0,0,1], [0,1,0], [1,-1,-1], [1,0,1], [1,1,0]] sage: points = PointConfiguration(p) sage: triang = points.triangulate() - sage: triang.plot(axes=False) # optional - sage.plot + sage: triang.plot(axes=False) # needs sage.plot Graphics3d Object .. PLOT:: @@ -108,18 +108,19 @@ The standard example of a non-regular triangulation (requires TOPCOM):: - sage: PointConfiguration.set_engine('topcom') # optional - topcom + sage: # optional - topcom + sage: PointConfiguration.set_engine('topcom') sage: p = PointConfiguration([[-1,-5/9], [0,10/9], [1,-5/9], ....: [-2,-10/9], [0,20/9], [2,-10/9]]) - sage: p_regular = p.restrict_to_regular_triangulations(True) # optional - topcom - sage: regular = p_regular.triangulations_list() # optional - topcom - sage: p_nonregular = p.restrict_to_regular_triangulations(False) # optional - topcom - sage: nonregular = p_nonregular.triangulations_list() # optional - topcom - sage: len(regular) # optional - topcom + sage: p_regular = p.restrict_to_regular_triangulations(True) + sage: regular = p_regular.triangulations_list() + sage: p_nonregular = p.restrict_to_regular_triangulations(False) + sage: nonregular = p_nonregular.triangulations_list() + sage: len(regular) 16 - sage: len(nonregular) # optional - topcom + sage: len(nonregular) 2 - sage: nonregular[0].plot(aspect_ratio=1, axes=False) # optional - topcom sage.plot + sage: nonregular[0].plot(aspect_ratio=1, axes=False) # needs sage.plot Graphics object consisting of 25 graphics primitives sage: PointConfiguration.set_engine('internal') # to make doctests independent of TOPCOM @@ -375,14 +376,15 @@ def set_engine(cls, engine='auto'): EXAMPLES:: + sage: # optional - topcom sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) sage: p.set_engine('internal') # to make doctests independent of TOPCOM sage: p.triangulate() (<1,3,4>, <2,3,4>) - sage: p.set_engine('topcom') # optional - topcom - sage: p.triangulate() # optional - topcom + sage: p.set_engine('topcom') + sage: p.triangulate() (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>) - sage: p.set_engine('internal') # optional - topcom + sage: p.set_engine('internal') """ engine = engine.lower() if engine not in ['auto', 'topcom', 'internal']: @@ -738,13 +740,14 @@ def _TOPCOM_triangulate(self, verbose=True): EXAMPLES:: + sage: # optional - topcom sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) - sage: p.set_engine('topcom') # optional - topcom - sage: p._TOPCOM_triangulate(verbose=False) # optional - topcom + sage: p.set_engine('topcom') + sage: p._TOPCOM_triangulate(verbose=False) (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>) - sage: list( p.triangulate() ) # optional - topcom + sage: list( p.triangulate() ) [(0, 1, 2), (0, 1, 4), (0, 2, 4), (1, 2, 3)] - sage: p.set_engine('internal') # optional - topcom + sage: p.set_engine('internal') """ assert self._regular is not False, \ 'When asked for a single triangulation TOPCOM ' + \ @@ -787,7 +790,7 @@ def restrict_to_regular_triangulations(self, regular=True): fine, not necessarily regular. sage: len(p.triangulations_list()) 4 - sage: PointConfiguration.set_engine('topcom') # optional - topcom + sage: PointConfiguration.set_engine('topcom') sage: p_regular = p.restrict_to_regular_triangulations() # optional - topcom sage: len(p_regular.triangulations_list()) # optional - topcom 4 @@ -831,7 +834,7 @@ def restrict_to_connected_triangulations(self, connected=True): fine, not necessarily regular. sage: len(p.triangulations_list()) 4 - sage: PointConfiguration.set_engine('topcom') # optional - topcom + sage: PointConfiguration.set_engine('topcom') sage: p_all = p.restrict_to_connected_triangulations(connected=False) # optional - topcom sage: len(p_all.triangulations_list()) # optional - topcom 4 @@ -961,27 +964,28 @@ def triangulations(self, verbose=False): compute the triangulations. Using TOPCOM, we obtain the same triangulations but in a different order:: - sage: p.set_engine('topcom') # optional - topcom - sage: iter = p.triangulations() # optional - topcom - sage: next(iter) # optional - topcom + sage: # optional - topcom + sage: p.set_engine('topcom') + sage: iter = p.triangulations() + sage: next(iter) (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>) - sage: next(iter) # optional - topcom + sage: next(iter) (<0,1,3>, <0,1,4>, <0,2,3>, <0,2,4>) - sage: next(iter) # optional - topcom + sage: next(iter) (<1,2,3>, <1,2,4>) - sage: next(iter) # optional - topcom + sage: next(iter) (<1,3,4>, <2,3,4>) - sage: p.triangulations_list() # optional - topcom + sage: p.triangulations_list() [(<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>), (<0,1,3>, <0,1,4>, <0,2,3>, <0,2,4>), (<1,2,3>, <1,2,4>), (<1,3,4>, <2,3,4>)] - sage: p_fine = p.restrict_to_fine_triangulations() # optional - topcom - sage: p_fine.set_engine('topcom') # optional - topcom - sage: p_fine.triangulations_list() # optional - topcom + sage: p_fine = p.restrict_to_fine_triangulations() + sage: p_fine.set_engine('topcom') + sage: p_fine.triangulations_list() [(<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>), (<0,1,3>, <0,1,4>, <0,2,3>, <0,2,4>)] - sage: p.set_engine('internal') # optional - topcom + sage: p.set_engine('internal') """ if self._use_TOPCOM: for triangulation in self._TOPCOM_triangulations(verbose): @@ -1017,10 +1021,10 @@ def triangulations_list(self, verbose=False): [(<0,1,2>, <1,2,3>), (<0,1,3>, <0,2,3>)] sage: list(map(list, p.triangulations_list())) [[(0, 1, 2), (1, 2, 3)], [(0, 1, 3), (0, 2, 3)]] - sage: p.set_engine('topcom') # optional - topcom + sage: p.set_engine('topcom') sage: p.triangulations_list() # optional - topcom [(<0,1,2>, <1,2,3>), (<0,1,3>, <0,2,3>)] - sage: p.set_engine('internal') # optional - topcom + sage: p.set_engine('internal') """ return list(self.triangulations(verbose)) @@ -1049,12 +1053,13 @@ def triangulate(self, verbose=False): Using TOPCOM yields a different, but equally good, triangulation:: - sage: p.set_engine('topcom') # optional - topcom - sage: p.triangulate() # optional - topcom + sage: # optional - topcom + sage: p.set_engine('topcom') + sage: p.triangulate() (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>) - sage: list(p.triangulate()) # optional - topcom + sage: list(p.triangulate()) [(0, 1, 2), (0, 1, 4), (0, 2, 4), (1, 2, 3)] - sage: p.set_engine('internal') # optional - topcom + sage: p.set_engine('internal') """ if self._use_TOPCOM and self._regular is not False: try: @@ -1127,10 +1132,10 @@ def restricted_automorphism_group(self): sage: pyramid = PointConfiguration([[1,0,0], [0,1,1], [0,1,-1], ....: [0,-1,-1], [0,-1,1]]) - sage: G = pyramid.restricted_automorphism_group() # optional - sage.graphs sage.groups - sage: G == PermutationGroup([[(3,5)], [(2,3),(4,5)], [(2,4)]]) # optional - sage.graphs sage.groups + sage: G = pyramid.restricted_automorphism_group() # needs sage.graphs sage.groups + sage: G == PermutationGroup([[(3,5)], [(2,3),(4,5)], [(2,4)]]) # needs sage.graphs sage.groups True - sage: DihedralGroup(4).is_isomorphic(G) # optional - sage.graphs sage.groups + sage: DihedralGroup(4).is_isomorphic(G) # needs sage.graphs sage.groups True The square with an off-center point in the middle. Note that @@ -1138,9 +1143,9 @@ def restricted_automorphism_group(self): `D_4` of the convex hull:: sage: square = PointConfiguration([(3/4,3/4), (1,1), (1,-1), (-1,-1), (-1,1)]) - sage: square.restricted_automorphism_group() # optional - sage.graphs sage.groups + sage: square.restricted_automorphism_group() # needs sage.graphs sage.groups Permutation Group with generators [(3,5)] - sage: DihedralGroup(1).is_isomorphic(_) # optional - sage.graphs sage.groups + sage: DihedralGroup(1).is_isomorphic(_) # needs sage.graphs sage.groups True """ v_list = [ vector(p.projective()) for p in self ] @@ -1530,9 +1535,9 @@ def bistellar_flips(self): sage: pc.bistellar_flips() (((<0,1,3>, <0,2,3>), (<0,1,2>, <1,2,3>)),) sage: Tpos, Tneg = pc.bistellar_flips()[0] - sage: Tpos.plot(axes=False) # optional - sage.plot + sage: Tpos.plot(axes=False) # needs sage.plot Graphics object consisting of 11 graphics primitives - sage: Tneg.plot(axes=False) # optional - sage.plot + sage: Tneg.plot(axes=False) # needs sage.plot Graphics object consisting of 11 graphics primitives The 3d analog:: @@ -1547,7 +1552,7 @@ def bistellar_flips(self): sage: pc.bistellar_flips() (((<0,1,3>, <0,2,3>), (<0,1,2>, <1,2,3>)),) sage: Tpos, Tneg = pc.bistellar_flips()[0] - sage: Tpos.plot(axes=False) # optional - sage.plot + sage: Tpos.plot(axes=False) # needs sage.plot Graphics3d Object """ flips = [] @@ -2085,7 +2090,7 @@ def plot(self, **kwds): EXAMPLES:: sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) - sage: p.plot(axes=False) # optional - sage.plot + sage: p.plot(axes=False) # needs sage.plot Graphics object consisting of 5 graphics primitives .. PLOT:: diff --git a/src/sage/geometry/voronoi_diagram.py b/src/sage/geometry/voronoi_diagram.py index 1e9629aa646..0cea1e91377 100644 --- a/src/sage/geometry/voronoi_diagram.py +++ b/src/sage/geometry/voronoi_diagram.py @@ -51,18 +51,19 @@ class VoronoiDiagram(SageObject): Get the Voronoi diagram of a regular pentagon in ``AA^2``. All cells meet at the origin:: - sage: DV = VoronoiDiagram([[AA(c) for c in v] for v in polytopes.regular_polygon(5).vertices_list()]); DV # optional - sage.rings.number_field + sage: DV = VoronoiDiagram([[AA(c) for c in v] # needs sage.rings.number_field + ....: for v in polytopes.regular_polygon(5).vertices_list()]); DV The Voronoi diagram of 5 points of dimension 2 in the Algebraic Real Field - sage: all(P.contains([0, 0]) for P in DV.regions().values()) # optional - sage.rings.number_field + sage: all(P.contains([0, 0]) for P in DV.regions().values()) # needs sage.rings.number_field True - sage: any(P.interior_contains([0, 0]) for P in DV.regions().values()) # optional - sage.rings.number_field + sage: any(P.interior_contains([0, 0]) for P in DV.regions().values()) # needs sage.rings.number_field False If the vertices are not converted to ``AA`` before, the method throws an error:: - sage: polytopes.dodecahedron().vertices_list()[0][0].parent() # optional - sage.rings.number_field + sage: polytopes.dodecahedron().vertices_list()[0][0].parent() # needs sage.rings.number_field Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? - sage: VoronoiDiagram(polytopes.dodecahedron().vertices_list()) # optional - sage.rings.number_field + sage: VoronoiDiagram(polytopes.dodecahedron().vertices_list()) # needs sage.rings.number_field Traceback (most recent call last): ... NotImplementedError: Base ring of the Voronoi diagram must be @@ -230,9 +231,9 @@ def _repr_(self): EXAMPLES:: - sage: V = VoronoiDiagram(polytopes.regular_polygon(3).vertices()); V # optional - sage.rings.number_field + sage: V = VoronoiDiagram(polytopes.regular_polygon(3).vertices()); V # needs sage.rings.number_field The Voronoi diagram of 3 points of dimension 2 in the Algebraic Real Field - sage: VoronoiDiagram([]) # optional - sage.rings.number_field + sage: VoronoiDiagram([]) The empty Voronoi diagram. """ if self._n: @@ -260,18 +261,17 @@ def plot(self, cell_colors=None, **kwds): EXAMPLES:: - sage: P = [[0.671, 0.650], [0.258, 0.767], [0.562, 0.406], [0.254, 0.709], [0.493, 0.879]] - - sage: V = VoronoiDiagram(P); S=V.plot() # optional - sage.plot - sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false) # optional - sage.plot - - sage: S=V.plot(cell_colors={0:'red', 1:'blue', 2:'green', 3:'white', 4:'yellow'}) # optional - sage.plot - sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false) # optional - sage.plot - - sage: S=V.plot(cell_colors=['red','blue','red','white', 'white']) # optional - sage.plot - sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false) # optional - sage.plot - - sage: S=V.plot(cell_colors='something else') # optional - sage.plot + sage: # needs sage.plot + sage: P = [[0.671, 0.650], [0.258, 0.767], [0.562, 0.406], + ....: [0.254, 0.709], [0.493, 0.879]] + sage: V = VoronoiDiagram(P); S=V.plot() + sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false) + sage: S = V.plot(cell_colors={0: 'red', 1: 'blue', 2: 'green', + ....: 3: 'white', 4: 'yellow'}) + sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false) + sage: S = V.plot(cell_colors=['red', 'blue', 'red', 'white', 'white']) + sage: show(S, xmin=0, xmax=1, ymin=0, ymax=1, aspect_ratio=1, axes=false) + sage: S = V.plot(cell_colors='something else') Traceback (most recent call last): ... AssertionError: 'cell_colors' must be a list or a dictionary @@ -280,7 +280,7 @@ def plot(self, cell_colors=None, **kwds): Trying to plot a Voronoi diagram of dimension other than 2 gives an error:: - sage: VoronoiDiagram([[1, 2, 3], [6, 5, 4]]).plot() # optional - sage.plot + sage: VoronoiDiagram([[1, 2, 3], [6, 5, 4]]).plot() # needs sage.plot Traceback (most recent call last): ... NotImplementedError: Plotting of 3-dimensional Voronoi diagrams not