From 92709dbbb5f777b602b6a4d6b1e70712ac3e9bb4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 30 Apr 2023 11:20:45 -0700 Subject: [PATCH 1/5] sage.geometry: Add some # optional, reformat doctests --- src/sage/geometry/cone.py | 440 +++++----- src/sage/geometry/fan.py | 95 +- src/sage/geometry/fan_isomorphism.py | 2 +- src/sage/geometry/fan_morphism.py | 15 +- src/sage/geometry/hasse_diagram.py | 6 +- .../hyperplane_arrangement/arrangement.py | 795 ++++++++--------- .../hyperplane_arrangement/check_freeness.py | 1 + .../hyperplane_arrangement/hyperplane.py | 46 +- .../hyperplane_arrangement/library.py | 128 +-- .../geometry/hyperplane_arrangement/plot.py | 72 +- src/sage/geometry/integral_points.pxi | 50 +- src/sage/geometry/lattice_polytope.py | 276 +++--- .../geometry/polyhedron/backend_cdd_rdf.py | 2 + .../geometry/polyhedron/backend_normaliz.py | 827 +++++++++--------- src/sage/geometry/polyhedron/base.py | 122 +-- src/sage/geometry/polyhedron/base2.py | 7 +- src/sage/geometry/polyhedron/base4.py | 2 +- src/sage/geometry/polyhedron/base5.py | 195 +++-- src/sage/geometry/polyhedron/base6.py | 363 ++++---- src/sage/geometry/polyhedron/base7.py | 202 +++-- src/sage/geometry/polyhedron/base_QQ.py | 365 ++++---- src/sage/geometry/polyhedron/base_RDF.py | 2 + .../geometry/polyhedron/base_number_field.py | 38 +- .../combinatorial_polyhedron/base.pyx | 271 +++--- .../combinatorial_face.pyx | 2 +- .../polyhedron_face_lattice.pyx | 5 +- src/sage/geometry/polyhedron/constructor.py | 56 +- src/sage/geometry/polyhedron/face.py | 92 +- src/sage/geometry/polyhedron/library.py | 532 +++++------ src/sage/geometry/polyhedron/misc.py | 2 +- src/sage/geometry/polyhedron/parent.py | 151 ++-- src/sage/geometry/polyhedron/plot.py | 264 +++--- .../polyhedron/ppl_lattice_polytope.py | 203 ++--- src/sage/geometry/pseudolines.py | 46 +- src/sage/geometry/relative_interior.py | 12 +- src/sage/geometry/toric_plotter.py | 54 +- src/sage/geometry/triangulation/element.py | 65 +- .../triangulation/point_configuration.py | 250 +++--- 38 files changed, 3155 insertions(+), 2901 deletions(-) diff --git a/src/sage/geometry/cone.py b/src/sage/geometry/cone.py index 1d9b1b4f080..2b796e3de1a 100644 --- a/src/sage/geometry/cone.py +++ b/src/sage/geometry/cone.py @@ -129,31 +129,31 @@ You can work with subcones that form faces of other cones:: - sage: face = four_rays.faces(dim=2)[0] - sage: face + sage: face = four_rays.faces(dim=2)[0] # optional - sage.graphs + sage: face # optional - sage.graphs 2-d face of 3-d cone in 3-d lattice N - sage: face.rays() + sage: face.rays() # optional - sage.graphs N(-1, -1, 1), N(-1, 1, 1) in 3-d lattice N - sage: face.ambient_ray_indices() + sage: face.ambient_ray_indices() # optional - sage.graphs (2, 3) - sage: four_rays.rays(face.ambient_ray_indices()) + sage: four_rays.rays(face.ambient_ray_indices()) # optional - sage.graphs 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() - sage: [len(s) for s in L.level_sets()] + sage: L = four_rays.face_lattice() # optional - sage.graphs + sage: [len(s) for s in L.level_sets()] # optional - sage.graphs [1, 4, 4, 1] - sage: face = L.level_sets()[2][0] - sage: face.rays() + sage: face = L.level_sets()[2][0] # optional - sage.graphs + sage: face.rays() # optional - sage.graphs N(1, 1, 1), N(1, -1, 1) in 3-d lattice N - sage: L.hasse_diagram().neighbors_in(face) + sage: L.hasse_diagram().neighbors_in(face) # optional - sage.graphs [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 +572,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)]) + sage: _ambient_space_point(c, [1/2, 1/sqrt(3)]) # optional - sage.symbolic sage.rings.number_field (1/2, 0.5773502691896258?) - sage: _ambient_space_point(c, vector(AA,[1/2,1/sqrt(3)])) + sage: _ambient_space_point(c, vector(AA, [1/2, 1/sqrt(3)])) # optional - sage.symbolic sage.rings.number_field (1/2, 0.5773502691896258?) sage: _ambient_space_point(c, [1,1,3]) Traceback (most recent call last): @@ -592,9 +592,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]) + sage: _ambient_space_point(c, [1, pi]) # optional - sage.symbolic sage.rings.number_field (1.00000000000000, 3.14159265358979) - sage: _ambient_space_point(c, vector(SR,[1, pi])) + sage: _ambient_space_point(c, vector(SR,[1, pi])) # optional - sage.symbolic sage.rings.number_field (1.00000000000000, 3.14159265358979) """ @@ -1005,7 +1005,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) + sage: c.ambient_vector_space(AA) # optional - sage.rings.number_field Vector space of dimension 2 over Algebraic Real Field """ return self.lattice().vector_space(base_field=base_field) @@ -1098,7 +1098,7 @@ def plot(self, **options): EXAMPLES:: sage: quadrant = Cone([(1,0), (0,1)]) - sage: quadrant.plot() # optional - sage.plot + sage: quadrant.plot() # optional - sage.plot Graphics object consisting of 9 graphics primitives """ tp = ToricPlotter(options, self.lattice().degree(), self.rays()) @@ -1601,7 +1601,7 @@ def __getstate__(self): TESTS:: sage: C = Cone([(1,0)]) - sage: C.face_lattice() + sage: C.face_lattice() # optional - sage.graphs sage.combinat Finite lattice containing 2 elements with distinguished linear extension sage: C._test_pickling() sage: C2 = loads(dumps(C)); C2 @@ -1674,17 +1674,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))) + sage: c._contains((1, sqrt(2))) # optional - sage.symbolic True - sage: c._contains(vector(SR, [1,pi])) + sage: c._contains(vector(SR, [1, pi])) # optional - 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)) + sage: c._contains((1,I)) # optional - sage.symbolic False - sage: c._contains(vector(QQbar,[1,I])) + sage: c._contains(vector(QQbar, [1,I])) # optional - sage.symbolic False And we refuse to coerce elements of another lattice into ours:: @@ -1971,7 +1971,7 @@ def _latex_(self): sage: quadrant = Cone([(1,0), (0,1)]) sage: quadrant._latex_() '\\sigma^{2}' - sage: quadrant.facets()[0]._latex_() + sage: quadrant.facets()[0]._latex_() # optional - sage.graphs '\\sigma^{1} \\subset \\sigma^{2}' """ if self.ambient() is self: @@ -1995,7 +1995,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] + sage: quadrant.facets()[0] # optional - sage.graphs 1-d face of 2-d cone in 2-d lattice N """ result = "%d-d" % self.dim() @@ -2051,7 +2051,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)): + sage: for i, face in enumerate(octant.faces(1)): # optional - sage.graphs ....: if face.ray(0) != octant.ray(i): ....: print("Wrong order!") """ @@ -2096,12 +2096,12 @@ def adjacent(self): EXAMPLES:: sage: octant = Cone([(1,0,0), (0,1,0), (0,0,1)]) - sage: octant.adjacent() + sage: octant.adjacent() # optional - sage.graphs () - sage: one_face = octant.faces(1)[0] - sage: len(one_face.adjacent()) + sage: one_face = octant.faces(1)[0] # optional - sage.graphs + sage: len(one_face.adjacent()) # optional - sage.graphs 2 - sage: one_face.adjacent()[1] + sage: one_face.adjacent()[1] # optional - sage.graphs 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 +2111,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()) + sage: len(cone.adjacent()) # optional - sage.graphs 1 The second generating cone is adjacent to this one. Now we create the @@ -2120,7 +2120,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()) + sage: len(cone.adjacent()) # optional - sage.graphs 1 The result is as before, since we still have:: @@ -2133,7 +2133,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()) + sage: len(cone.adjacent()) # optional - sage.graphs 0 Since now ``cone`` has smaller dimension than ``fan``, it and its @@ -2176,12 +2176,12 @@ def ambient(self): 3-d cone in 3-d lattice N sage: cone.ambient() is cone True - sage: face = cone.faces(1)[0] - sage: face + sage: face = cone.faces(1)[0] # optional - sage.graphs + sage: face # optional - sage.graphs 1-d face of 3-d cone in 3-d lattice N - sage: face.ambient() + sage: face.ambient() # optional - sage.graphs 3-d cone in 3-d lattice N - sage: face.ambient() is cone + sage: face.ambient() is cone # optional - sage.graphs True """ return self._ambient @@ -2199,7 +2199,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() + sage: quadrant.facets()[1].ambient_ray_indices() # optional - sage.graphs (1,) """ return self._ambient_ray_indices @@ -2232,15 +2232,15 @@ def contains(self, *args): True sage: c.contains((-1,0)) False - sage: c.contains(c.dual_lattice()(1,0)) #random output (warning) + sage: c.contains(c.dual_lattice()(1,0)) # random output (warning) False sage: c.contains(c.dual_lattice()(1,0)) False sage: c.contains(1) False - sage: c.contains(1/2, sqrt(3)) + sage: c.contains(1/2, sqrt(3)) # optional - sage.symbolic True - sage: c.contains(-1/2, sqrt(3)) + sage: c.contains(-1/2, sqrt(3)) # optional - sage.symbolic False """ point = flatten(args) @@ -2369,7 +2369,7 @@ def embed(self, cone): 1-d cone in 3-d lattice N sage: ray.ambient_ray_indices() (0,) - sage: ray.adjacent() + sage: ray.adjacent() # optional - sage.graphs () sage: ray.ambient() 1-d cone in 3-d lattice N @@ -2377,22 +2377,22 @@ 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) - sage: e_ray + sage: e_ray = c.embed(ray) # optional - sage.graphs + sage: e_ray # optional - sage.graphs 1-d face of 3-d cone in 3-d lattice N - sage: e_ray.rays() + sage: e_ray.rays() # optional - sage.graphs N(0, -1, 1) in 3-d lattice N - sage: e_ray is ray + sage: e_ray is ray # optional - sage.graphs False - sage: e_ray.is_equivalent(ray) + sage: e_ray.is_equivalent(ray) # optional - sage.graphs True - sage: e_ray.ambient_ray_indices() + sage: e_ray.ambient_ray_indices() # optional - sage.graphs (3,) - sage: e_ray.adjacent() + sage: e_ray.adjacent() # optional - sage.graphs (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() + sage: e_ray.ambient() # optional - sage.graphs 3-d cone in 3-d lattice N Not every cone can be embedded into a fixed ambient cone:: @@ -2402,7 +2402,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)])) + sage: c.embed(Cone([(1,0,1), (-1,0,1)])) # optional - sage.graphs Traceback (most recent call last): ... ValueError: 2-d cone in 3-d lattice N is not a face @@ -2447,13 +2447,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() - sage: L + sage: L = quadrant.face_lattice() # optional - sage.graphs sage.combinat + sage: L # optional - sage.graphs sage.combinat 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) + sage: for level in L.level_sets(): print(level) # optional - sage.graphs sage.combinat [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 +2461,15 @@ def face_lattice(self): For a particular face you can look at its actual rays... :: - sage: face = L.level_sets()[1][0] - sage: face.rays() + sage: face = L.level_sets()[1][0] # optional - sage.graphs sage.combinat + sage: face.rays() # optional - sage.graphs sage.combinat 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() + sage: face.ambient_ray_indices() # optional - sage.graphs sage.combinat (0,) sage: quadrant.ray(0) N(1, 0) @@ -2477,34 +2477,34 @@ 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] + sage: face is quadrant.faces(dim=1)[0] # optional - sage.graphs sage.combinat 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] - sage: D = L.hasse_diagram() - sage: sorted(D.neighbors(face)) + 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 [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] - sage: face + sage: face = quadrant.faces(1)[0] # optional - sage.graphs + sage: face # optional - sage.graphs 1-d face of 2-d cone in 2-d lattice N - sage: face.rays() + sage: face.rays() # optional - sage.graphs N(1, 0) in 2-d lattice N - sage: face.facets() + sage: face.facets() # optional - sage.graphs (0-d face of 2-d cone in 2-d lattice N,) - sage: face.facet_of() + sage: face.facet_of() # optional - sage.graphs (2-d cone in 2-d lattice N,) - sage: face.adjacent() + sage: face.adjacent() # optional - sage.graphs (1-d face of 2-d cone in 2-d lattice N,) - sage: face.adjacent()[0].rays() + sage: face.adjacent()[0].rays() # optional - sage.graphs N(0, 1) in 2-d lattice N @@ -2513,20 +2513,20 @@ def face_lattice(self): sage: supercone = Cone([(1,2,3,4), (5,6,7,8), ....: (1,2,4,8), (1,3,9,7)]) - sage: supercone.face_lattice() + sage: supercone.face_lattice() # optional - sage.graphs sage.combinat Finite lattice containing 16 elements with distinguished linear extension - sage: supercone.face_lattice().top() + sage: supercone.face_lattice().top() # optional - sage.graphs sage.combinat 4-d cone in 4-d lattice N - sage: cone = supercone.facets()[0] - sage: cone + sage: cone = supercone.facets()[0] # optional - sage.graphs sage.combinat + sage: cone # optional - sage.graphs sage.combinat 3-d face of 4-d cone in 4-d lattice N - sage: cone.face_lattice() + sage: cone.face_lattice() # optional - sage.graphs sage.combinat Finite poset containing 8 elements with distinguished linear extension - sage: cone.face_lattice().bottom() + sage: cone.face_lattice().bottom() # optional - sage.graphs sage.combinat 0-d face of 4-d cone in 4-d lattice N - sage: cone.face_lattice().top() + sage: cone.face_lattice().top() # optional - sage.graphs sage.combinat 3-d face of 4-d cone in 4-d lattice N - sage: cone.face_lattice().top() == cone + sage: cone.face_lattice().top() == cone # optional - sage.graphs sage.combinat True TESTS:: @@ -2542,19 +2542,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() + sage: C1.face_lattice() is C2.face_lattice() # optional - sage.graphs sage.combinat False - sage: C1.facets()[0] + sage: C1.facets()[0] # optional - sage.graphs 0-d face of 1-d cone in 2-d lattice N - sage: C2.facets()[0] + sage: C2.facets()[0] # optional - sage.graphs 0-d face of 1-d cone in 2-d lattice N - sage: C1.facets()[0].ambient() is C1 + sage: C1.facets()[0].ambient() is C1 # optional - sage.graphs True - sage: C2.facets()[0].ambient() is C1 + sage: C2.facets()[0].ambient() is C1 # optional - sage.graphs False - sage: C2.facets()[0].ambient() is C2 + sage: C2.facets()[0].ambient() is C2 # optional - sage.graphs True """ if "_face_lattice" not in self.__dict__: @@ -2680,50 +2680,50 @@ 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() + sage: quadrant.faces() # optional - 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) + sage: quadrant.faces(dim=1) # optional - 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] + sage: face = quadrant.faces(dim=1)[0] # optional - sage.graphs Now you can look at the actual rays of this face... :: - sage: face.rays() + sage: face.rays() # optional - 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() + sage: face.ambient_ray_indices() # optional - 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) + sage: quadrant.faces(-1) # optional - sage.graphs () - sage: quadrant.faces(3) + sage: quadrant.faces(3) # optional - sage.graphs () In the case of non-strictly convex cones even faces of small non-negative dimension may be missing:: sage: halfplane = Cone([(1,0), (0,1), (-1,0)]) - sage: halfplane.faces(0) + sage: halfplane.faces(0) # optional - sage.graphs () - sage: halfplane.faces() + sage: halfplane.faces() # optional - sage.graphs ((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)]) - sage: plane.faces(1) + sage: plane = Cone([(1,0), (0,1), (-1,-1)]) # optional - sage.graphs + sage: plane.faces(1) # optional - sage.graphs () - sage: plane.faces() + sage: plane.faces() # optional - sage.graphs ((2-d cone in 2-d lattice N,),) TESTS: @@ -2732,7 +2732,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() + sage: c.faces() # optional - 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, @@ -2747,14 +2747,14 @@ def faces(self, dim=None, codim=None): sage: cone = toric_varieties.dP8().fan().generating_cone(0); cone # optional - palp 2-d cone of Rational polyhedral fan in 2-d lattice N - sage: for f in cone.facets(): print(f.rays()) # optional - palp + sage: for f in cone.facets(): print(f.rays()) # optional - palp sage.graphs N(1, 1) in 2-d lattice N N(0, 1) in 2-d lattice N - sage: len(cone.faces()) # optional - palp + sage: len(cone.faces()) # optional - palp sage.graphs 3 - sage: for f in cone.facets(): print(f.rays()) # optional - palp + sage: for f in cone.facets(): print(f.rays()) # optional - palp sage.graphs N(1, 1) in 2-d lattice N N(0, 1) @@ -2901,25 +2901,25 @@ def facet_of(self): EXAMPLES:: sage: octant = Cone([(1,0,0), (0,1,0), (0,0,1)]) - sage: octant.facet_of() + sage: octant.facet_of() # optional - sage.graphs () - sage: one_face = octant.faces(1)[0] - sage: len(one_face.facet_of()) + sage: one_face = octant.faces(1)[0] # optional - sage.graphs + sage: len(one_face.facet_of()) # optional - sage.graphs 2 - sage: one_face.facet_of()[1] + sage: one_face.facet_of()[1] # optional - sage.graphs 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() + sage: fan.generating_cone(0).facet_of() # optional - sage.graphs () Subcones of generating cones work as before:: - sage: one_cone = fan(1)[0] - sage: len(one_cone.facet_of()) + sage: one_cone = fan(1)[0] # optional - sage.graphs + sage: len(one_cone.facet_of()) # optional - sage.graphs 2 """ L = self._ambient._face_lattice_function() @@ -2938,7 +2938,7 @@ def facets(self): EXAMPLES:: sage: quadrant = Cone([(1,0), (0,1)]) - sage: quadrant.facets() + sage: quadrant.facets() # optional - 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 +3257,19 @@ def is_isomorphic(self, other): We check that :trac:`18613` is fixed:: sage: K = cones.trivial(0) - sage: K.is_isomorphic(K) + sage: K.is_isomorphic(K) # optional - sage.graphs True sage: K = cones.trivial(1) - sage: K.is_isomorphic(K) + sage: K.is_isomorphic(K) # optional - sage.graphs True sage: K = cones.trivial(2) - sage: K.is_isomorphic(K) + sage: K.is_isomorphic(K) # optional - sage.graphs 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) + sage: K.is_isomorphic(K) # optional - sage.graphs True """ if self.is_strictly_convex() and other.is_strictly_convex(): @@ -3484,7 +3484,7 @@ def plot(self, **options): EXAMPLES:: sage: quadrant = Cone([(1,0), (0,1)]) - sage: quadrant.plot() # optional - sage.plot + sage: quadrant.plot() # optional - 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 +3754,7 @@ def solid_restriction(self): the original:: sage: K = random_cone(max_ambient_dim=6) - sage: len(K.solid_restriction().facets()) == len(K.facets()) + sage: len(K.solid_restriction().facets()) == len(K.facets()) # optional - sage.graphs True """ if self.is_solid(): @@ -3915,17 +3915,17 @@ def sublattice_quotient(self, *args, **kwds): EXAMPLES:: - sage: C2_Z2 = Cone([(1,0),(1,2)]) # C^2/Z_2 - sage: c1, c2 = C2_Z2.facets() - sage: c2.sublattice_quotient() + 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 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 + sage: n_bar = c2.sublattice_quotient(n); n_bar # optional - sage.graphs N[1, 1] - sage: n_bar.lift() + sage: n_bar.lift() # optional - sage.graphs N(1, 1) - sage: vector(n_bar) + sage: vector(n_bar) # optional - sage.graphs (-1) """ if "_sublattice_quotient" not in self.__dict__: @@ -3967,11 +3967,11 @@ 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() - sage: c2.sublattice() + 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 Sublattice - sage: c2.sublattice_complement() + sage: c2.sublattice_complement() # optional - sage.graphs Sublattice A more complicated example:: @@ -4197,30 +4197,30 @@ def relative_orthogonal_quotient(self, supercone): EXAMPLES:: - sage: rho = Cone([(1,1,1,3),(1,-1,1,3),(-1,-1,1,3),(-1,1,1,3)]) + 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] - sage: sigma.orthogonal_sublattice() + sage: sigma = rho.facets()[1] # optional - sage.graphs + sage: sigma.orthogonal_sublattice() # optional - sage.graphs Sublattice - sage: sigma.is_face_of(rho) + sage: sigma.is_face_of(rho) # optional - sage.graphs True - sage: Q = sigma.relative_orthogonal_quotient(rho); Q + sage: Q = sigma.relative_orthogonal_quotient(rho); Q # optional - sage.graphs 1-d lattice, quotient of Sublattice by Sublattice - sage: Q.gens() + sage: Q.gens() # optional - sage.graphs (M[0, 1, 1, 0],) Different codimension:: sage: rho = Cone([[1,-1,1,3],[-1,-1,1,3]]) - sage: sigma = rho.facets()[0] - sage: sigma.orthogonal_sublattice() + sage: sigma = rho.facets()[0] # optional - sage.graphs + sage: sigma.orthogonal_sublattice() # optional - sage.graphs Sublattice - sage: rho.orthogonal_sublattice() + sage: rho.orthogonal_sublattice() # optional - sage.graphs Sublattice - sage: sigma.relative_orthogonal_quotient(rho).gens() + sage: sigma.relative_orthogonal_quotient(rho).gens() # optional - sage.graphs (M[-1, 0, -2, 1],) Sign choice in the codimension one case:: @@ -4280,7 +4280,7 @@ def semigroup_generators(self): We start with a simple case of a non-smooth 2-dimensional cone:: - sage: Cone([ (1,0), (1,2) ]).semigroup_generators() + sage: Cone([(1,0), (1,2)]).semigroup_generators() N(1, 1), N(1, 0), N(1, 2) @@ -4294,19 +4294,19 @@ def semigroup_generators(self): GAP's toric package thinks this is challenging:: - sage: cone = Cone([[1,2,3,4],[0,1,0,7],[3,1,0,2],[0,0,1,0]]).dual() - sage: len( cone.semigroup_generators() ) + sage: cone = Cone([[1,2,3,4], [0,1,0,7], [3,1,0,2], [0,0,1,0]]).dual() + sage: len(cone.semigroup_generators()) 2806 The cone need not be strictly convex:: - sage: halfplane = Cone([(1,0),(2,1),(-1,0)]) + sage: halfplane = Cone([(1,0), (2,1), (-1,0)]) sage: sorted(halfplane.semigroup_generators()) [N(-1, 0), N(0, 1), N(1, 0)] - sage: line = Cone([(1,1,1),(-1,-1,-1)]) + sage: line = Cone([(1,1,1), (-1,-1,-1)]) sage: sorted(line.semigroup_generators()) [N(-1, -1, -1), N(1, 1, 1)] - sage: wedge = Cone([ (1,0,0), (1,2,0), (0,0,1), (0,0,-1) ]) + sage: wedge = Cone([(1,0,0), (1,2,0), (0,0,1), (0,0,-1)]) sage: sorted(wedge.semigroup_generators()) [N(0, 0, -1), N(0, 0, 1), N(1, 0, 0), N(1, 1, 0), N(1, 2, 0)] @@ -4324,14 +4324,14 @@ def semigroup_generators(self): sage: A.elementary_divisors() [1, 1, 1, 0] sage: cone3d = Cone([(3,0,-1), (1,-1,0), (0,1,0), (0,0,1)]) - sage: rays = ( A*vector(v) for v in cone3d.rays() ) + sage: rays = (A*vector(v) for v in cone3d.rays()) sage: gens = Cone(rays).semigroup_generators(); sorted(gens) [N(-2, -1, 0, 17), N(0, 1, -2, 0), N(1, -1, 1, 15), N(3, -4, 5, 45), N(3, 0, 1, -2)] - sage: set(map(tuple,gens)) == set( tuple(A*r) for r in cone3d.semigroup_generators() ) + sage: set(map(tuple,gens)) == set(tuple(A*r) for r in cone3d.semigroup_generators()) True TESTS:: @@ -4425,7 +4425,7 @@ def Hilbert_basis(self): We start with a simple case of a non-smooth 2-dimensional cone:: - sage: Cone([ (1,0), (1,2) ]).Hilbert_basis() + sage: Cone([(1,0), (1,2)]).Hilbert_basis() N(1, 0), N(1, 2), N(1, 1) @@ -4433,14 +4433,14 @@ def Hilbert_basis(self): Two more complicated example from GAP/toric:: - sage: Cone([[1,0],[3,4]]).dual().Hilbert_basis() + sage: Cone([[1,0], [3,4]]).dual().Hilbert_basis() M(0, 1), M(4, -3), M(1, 0), M(2, -1), M(3, -2) in 2-d lattice M - sage: cone = Cone([[1,2,3,4],[0,1,0,7],[3,1,0,2],[0,0,1,0]]).dual() + sage: cone = Cone([[1,2,3,4], [0,1,0,7], [3,1,0,2], [0,0,1,0]]).dual() sage: cone.Hilbert_basis() # long time M(10, -7, 0, 1), M(-5, 21, 0, -3), @@ -4475,7 +4475,7 @@ def Hilbert_basis(self): Not a strictly convex cone:: - sage: wedge = Cone([ (1,0,0), (1,2,0), (0,0,1), (0,0,-1) ]) + sage: wedge = Cone([(1,0,0), (1,2,0), (0,0,1), (0,0,-1)]) sage: sorted(wedge.semigroup_generators()) [N(0, 0, -1), N(0, 0, 1), N(1, 0, 0), N(1, 1, 0), N(1, 2, 0)] sage: wedge.Hilbert_basis() @@ -4573,7 +4573,7 @@ def Hilbert_coefficients(self, point, solver=None, verbose=0, EXAMPLES:: - sage: cone = Cone([(1,0),(0,1)]) + sage: cone = Cone([(1,0), (0,1)]) sage: cone.rays() N(1, 0), N(0, 1) @@ -4584,19 +4584,19 @@ def Hilbert_coefficients(self, point, solver=None, verbose=0, A more complicated example:: sage: N = ToricLattice(2) - sage: cone = Cone([N(1,0),N(1,2)]) + sage: cone = Cone([N(1,0), N(1,2)]) sage: cone.Hilbert_basis() N(1, 0), N(1, 2), N(1, 1) in 2-d lattice N - sage: cone.Hilbert_coefficients( N(1,1) ) + sage: cone.Hilbert_coefficients(N(1,1)) (0, 0, 1) The cone need not be strictly convex:: sage: N = ToricLattice(3) - sage: cone = Cone([N(1,0,0),N(1,2,0),N(0,0,1),N(0,0,-1)]) + sage: cone = Cone([N(1,0,0), N(1,2,0), N(0,0,1), N(0,0,-1)]) sage: cone.Hilbert_basis() N(1, 2, 0), N(1, 0, 0), @@ -4604,7 +4604,7 @@ def Hilbert_coefficients(self, point, solver=None, verbose=0, N(0, 0, -1), N(1, 1, 0) in 3-d lattice N - sage: cone.Hilbert_coefficients( N(1,1,3) ) + sage: cone.Hilbert_coefficients(N(1,1,3)) (0, 0, 3, 0, 1) """ point = self.lattice()(point) @@ -4663,7 +4663,7 @@ def is_solid(self): A closed convex cone is solid if and only if its dual is strictly convex:: - sage: K = random_cone(max_ambient_dim = 8) + sage: K = random_cone(max_ambient_dim=8) sage: K.is_solid() == K.dual().is_strictly_convex() True """ @@ -4710,7 +4710,7 @@ def is_proper(self): Likewise, a half-space contains at least one line, so it is not proper:: - sage: halfspace = Cone([(1,0),(0,1),(-1,0)]) + sage: halfspace = Cone([(1,0), (0,1), (-1,0)]) sage: halfspace.is_proper() False @@ -4746,14 +4746,14 @@ def is_full_space(self): The right half-space contains a vector subspace, but it is still not equal to the entire space:: - sage: K = Cone([(1,0),(-1,0),(0,1)]) + sage: K = Cone([(1,0), (-1,0), (0,1)]) sage: K.is_full_space() False However, if we allow conic combinations of both axes, then the resulting cone is the entire two-dimensional space:: - sage: K = Cone([(1,0),(-1,0),(0,1),(0,-1)]) + sage: K = Cone([(1,0), (-1,0), (0,1), (0,-1)]) sage: K.is_full_space() True @@ -4817,7 +4817,7 @@ def lineality(self): The lineality of a cone should be an integer between zero and the dimension of the ambient space, inclusive:: - sage: K = random_cone(max_ambient_dim = 8) + sage: K = random_cone(max_ambient_dim=8) sage: l = K.lineality() sage: l in ZZ True @@ -4826,7 +4826,7 @@ def lineality(self): A strictly convex cone should have lineality zero:: - sage: K = random_cone(max_ambient_dim = 8, strictly_convex = True) + sage: K = random_cone(max_ambient_dim=8, strictly_convex=True) sage: K.lineality() 0 """ @@ -4904,7 +4904,7 @@ def discrete_complementarity_set(self): When a cone is the entire space, its dual is the trivial cone, so the only discrete complementarity set for it is empty:: - sage: K = Cone([(1,0),(-1,0),(0,1),(0,-1)]) + sage: K = Cone([(1,0), (-1,0), (0,1), (0,-1)]) sage: K.is_full_space() True sage: K.discrete_complementarity_set() @@ -4923,7 +4923,7 @@ def discrete_complementarity_set(self): sage: K = random_cone(max_ambient_dim=6) sage: dcs_dual = K.dual().discrete_complementarity_set() - sage: expected = tuple( (x,s) for (s,x) in dcs_dual ) + sage: expected = tuple((x,s) for (s,x) in dcs_dual) sage: actual = K.discrete_complementarity_set() sage: sorted(actual) == sorted(expected) True @@ -4933,7 +4933,7 @@ def discrete_complementarity_set(self): sage: K = random_cone(max_ambient_dim=6) sage: dcs = K.discrete_complementarity_set() - sage: sum( (s*x).abs() for (x,s) in dcs ) + sage: sum((s*x).abs() for (x,s) in dcs) 0 """ # Return an immutable tuple instead of a mutable list because @@ -5042,7 +5042,7 @@ def lyapunov_like_basis(self): sage: K = random_cone(max_ambient_dim=8) sage: LL = K.lyapunov_like_basis() - sage: all( L.is_lyapunov_like_on(K) for L in LL ) + sage: all(L.is_lyapunov_like_on(K) for L in LL) True The Lyapunov-like transformations on a cone and its dual are @@ -5053,8 +5053,8 @@ def lyapunov_like_basis(self): sage: LL1 = K.lyapunov_like_basis() sage: LL2 = (L.transpose() for L in K.dual().lyapunov_like_basis()) sage: V = VectorSpace(K.lattice().base_field(), K.lattice_dim()^2) - sage: LL1_vecs = ( V(m.list()) for m in LL1 ) - sage: LL2_vecs = ( V(m.list()) for m in LL2 ) + sage: LL1_vecs = (V(m.list()) for m in LL1) + sage: LL2_vecs = (V(m.list()) for m in LL2) sage: V.span(LL1_vecs) == V.span(LL2_vecs) True @@ -5065,9 +5065,9 @@ def lyapunov_like_basis(self): sage: LL = K.lyapunov_like_basis() sage: W = VectorSpace(K.lattice().base_field(), K.lattice_dim()**2) sage: LL_W = W.span( W(m.list()) for m in LL ) - sage: brackets = ( W((L1*L2 - L2*L1).list()) for L1 in LL - ....: for L2 in LL ) - sage: all( b in LL_W for b in brackets ) + sage: brackets = (W((L1*L2 - L2*L1).list()) for L1 in LL + ....: for L2 in LL) + sage: all(b in LL_W for b in brackets) True """ # Matrices are not vectors in Sage, so we have to convert them @@ -5149,7 +5149,7 @@ def lyapunov_rank(self): [Or2017]_:: sage: Q5 = VectorSpace(QQ, 5) - sage: gs = Q5.basis() + [ -r for r in Q5.basis() ] + sage: gs = Q5.basis() + [-r for r in Q5.basis()] sage: K = Cone(gs) sage: K.lyapunov_rank() 25 @@ -5229,7 +5229,7 @@ def lyapunov_rank(self): sage: K1 = random_cone(max_ambient_dim=8) sage: n = K1.lattice_dim() sage: A = random_matrix(QQ, n, algorithm='unimodular') - sage: K2 = Cone( ( A*r for r in K1 ), lattice=K1.lattice()) + sage: K2 = Cone((A*r for r in K1), lattice=K1.lattice()) sage: K1.lyapunov_rank() == K2.lyapunov_rank() True @@ -5286,7 +5286,7 @@ def lyapunov_rank(self): sage: K = random_cone(max_ambient_dim=8) sage: L = ToricLattice(K.lattice_dim() + 1) - sage: K = Cone([ r.list() + [0] for r in K ], lattice=L) + sage: K = Cone([r.list() + [0] for r in K], lattice=L) sage: K.lyapunov_rank() >= K.lattice_dim() True """ @@ -5360,14 +5360,14 @@ def random_element(self, ring=ZZ): components nonnegative:: sage: K = cones.nonnegative_orthant(3) - sage: all( x >= 0 for x in K.random_element() ) + sage: all(x >= 0 for x in K.random_element()) True - sage: all( x >= 0 for x in K.random_element(ring=QQ) ) + sage: all(x >= 0 for x in K.random_element(ring=QQ)) True If ``ring`` is not ``ZZ`` or ``QQ``, an error is raised:: - sage: K = Cone([(1,0),(0,1)]) + sage: K = Cone([(1,0), (0,1)]) sage: K.random_element(ring=RR) Traceback (most recent call last): ... @@ -5516,7 +5516,7 @@ def positive_operators_gens(self, K2=None): sage: K.positive_operators_gens() [[1]] - sage: K = Cone([(1,0),(0,1)]) + sage: K = Cone([(1,0), (0,1)]) sage: K.positive_operators_gens() [ [1 0] [0 1] [0 0] [0 0] @@ -5546,13 +5546,13 @@ def positive_operators_gens(self, K2=None): Every operator is positive on the ambient vector space:: - sage: K = Cone([(1,),(-1,)]) + sage: K = Cone([(1,), (-1,)]) sage: K.is_full_space() True sage: K.positive_operators_gens() [[1], [-1]] - sage: K = Cone([(1,0),(-1,0),(0,1),(0,-1)]) + sage: K = Cone([(1,0), (-1,0), (0,1), (0,-1)]) sage: K.is_full_space() True sage: K.positive_operators_gens() @@ -5564,7 +5564,7 @@ def positive_operators_gens(self, K2=None): A non-obvious application is to find the positive operators on the right half-plane [Or2018b]_:: - sage: K = Cone([(1,0),(0,1),(0,-1)]) + sage: K = Cone([(1,0), (0,1), (0,-1)]) sage: K.positive_operators_gens() [ [1 0] [0 0] [ 0 0] [0 0] [ 0 0] @@ -5580,7 +5580,7 @@ def positive_operators_gens(self, K2=None): sage: K2 = random_cone(max_ambient_dim=3) sage: pi_gens = K1.positive_operators_gens(K2) sage: L = ToricLattice(K1.lattice_dim() * K2.lattice_dim()) - sage: pi_cone = Cone(( g.list() for g in pi_gens ), + sage: pi_cone = Cone((g.list() for g in pi_gens), ....: lattice=L, ....: check=False) sage: P = matrix(K2.lattice_dim(), @@ -5596,16 +5596,16 @@ def positive_operators_gens(self, K2=None): sage: K = random_cone(max_ambient_dim=3) sage: pi_gens = K.positive_operators_gens() sage: L = ToricLattice(K.lattice_dim()**2) - sage: pi_cone = Cone(( g.list() for g in pi_gens ), + sage: pi_cone = Cone((g.list() for g in pi_gens), ....: lattice=L, ....: check=False) sage: actual = pi_cone.dual().linear_subspace() - sage: U1 = [ vector((s.tensor_product(x)).list()) - ....: for x in K.lines() - ....: for s in K.dual() ] - sage: U2 = [ vector((s.tensor_product(x)).list()) - ....: for x in K - ....: for s in K.dual().lines() ] + sage: U1 = [vector((s.tensor_product(x)).list()) + ....: for x in K.lines() + ....: for s in K.dual()] + sage: U2 = [vector((s.tensor_product(x)).list()) + ....: for x in K + ....: for s in K.dual().lines()] sage: expected = pi_cone.lattice().vector_space().span(U1+U2) sage: actual == expected True @@ -5667,7 +5667,7 @@ def positive_operators_gens(self, K2=None): sage: pi_cone.dim() == n^2 True - sage: K = Cone([(1,0),(0,1),(0,-1)]) + sage: K = Cone([(1,0), (0,1), (0,-1)]) sage: pi_gens = K.positive_operators_gens() sage: pi_cone = Cone((g.list() for g in pi_gens), ....: check=False) @@ -5712,7 +5712,7 @@ def positive_operators_gens(self, K2=None): sage: pi_cone.lineality() == n^2 True - sage: K = Cone([(1,0),(0,1),(0,-1)]) + sage: K = Cone([(1,0), (0,1), (0,-1)]) sage: pi_gens = K.positive_operators_gens() sage: pi_cone = Cone((g.list() for g in pi_gens), check=False) sage: pi_cone.lineality() == 2 @@ -5735,17 +5735,17 @@ def positive_operators_gens(self, K2=None): sage: K = random_cone(max_ambient_dim=3) sage: L = ToricLattice(K.lattice_dim()**2) - 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), + 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 ....: lattice=L, ....: check=False) sage: pi_gens = K.positive_operators_gens() - sage: expected = Cone(((p*g*p.inverse()).list() for g in pi_gens), + sage: expected = Cone(((p*g*p.inverse()).list() for g in pi_gens), # optional - sage.groups ....: lattice=L, ....: check=False) - sage: actual.is_equivalent(expected) + sage: actual.is_equivalent(expected) # optional - sage.groups True An operator is positive from one cone to another if and only if @@ -5813,16 +5813,16 @@ def positive_operators_gens(self, K2=None): sage: L = ToricLattice(m*n) sage: M1 = MatrixSpace(F, m, m) sage: M2 = MatrixSpace(F, n, n) - sage: tps = ( M2(s.list()).tensor_product(M1(x.list())) - ....: for x in K1.dual().lyapunov_like_basis() - ....: for s in K2.lyapunov_like_basis() ) + sage: tps = (M2(s.list()).tensor_product(M1(x.list())) + ....: for x in K1.dual().lyapunov_like_basis() + ....: for s in K2.lyapunov_like_basis()) sage: W = VectorSpace(F, (m**2)*(n**2)) - sage: expected = span(F, ( W(x.list()) for x in tps )) + sage: expected = span(F, (W(x.list()) for x in tps)) sage: pi_cone = Cone((g.list() for g in pi_gens), ....: lattice=L, ....: check=False) sage: LL_pi = pi_cone.lyapunov_like_basis() - sage: actual = span(F, ( W(x.list()) for x in LL_pi )) + sage: actual = span(F, (W(x.list()) for x in LL_pi)) sage: actual == expected True """ @@ -5922,11 +5922,11 @@ def cross_positive_operators_gens(self): [0 1] [0 0] [1 0] [-1 0] [0 0] [ 0 0] [0 0], [1 0], [0 0], [ 0 0], [0 1], [ 0 -1] ] - sage: K = Cone([(1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1)]) - sage: all( c[i][j] >= 0 for c in K.cross_positive_operators_gens() - ....: for i in range(c.nrows()) - ....: for j in range(c.ncols()) - ....: if i != j ) + sage: K = Cone([(1,0,0,0), (0,1,0,0), (0,0,1,0), (0,0,0,1)]) + sage: all(c[i][j] >= 0 for c in K.cross_positive_operators_gens() + ....: for i in range(c.nrows()) + ....: for j in range(c.ncols()) + ....: if i != j) True The trivial cone in a trivial space has no cross-positive @@ -5939,13 +5939,13 @@ def cross_positive_operators_gens(self): Every operator is a cross-positive operator on the ambient vector space:: - sage: K = Cone([(1,),(-1,)]) + sage: K = Cone([(1,), (-1,)]) sage: K.is_full_space() True sage: K.cross_positive_operators_gens() [[1], [-1]] - sage: K = Cone([(1,0),(-1,0),(0,1),(0,-1)]) + sage: K = Cone([(1,0), (-1,0), (0,1), (0,-1)]) sage: K.is_full_space() True sage: K.cross_positive_operators_gens() @@ -5957,7 +5957,7 @@ def cross_positive_operators_gens(self): A non-obvious application is to find the cross-positive operators on the right half-plane [Or2018b]_:: - sage: K = Cone([(1,0),(0,1),(0,-1)]) + sage: K = Cone([(1,0), (0,1), (0,-1)]) sage: K.cross_positive_operators_gens() [ [1 0] [-1 0] [0 0] [ 0 0] [0 0] [ 0 0] @@ -5967,13 +5967,13 @@ def cross_positive_operators_gens(self): Cross-positive operators on a subspace are Lyapunov-like and vice-versa:: - sage: K = Cone([(1,0),(-1,0),(0,1),(0,-1)]) + sage: K = Cone([(1,0), (-1,0), (0,1), (0,-1)]) sage: K.is_full_space() True - sage: lls = span( vector(l.list()) - ....: for l in K.lyapunov_like_basis() ) - sage: cs = span( vector(c.list()) - ....: for c in K.cross_positive_operators_gens() ) + sage: lls = span(vector(l.list()) + ....: for l in K.lyapunov_like_basis()) + sage: cs = span(vector(c.list()) + ....: for c in K.cross_positive_operators_gens()) sage: cs == lls True @@ -5984,7 +5984,7 @@ def cross_positive_operators_gens(self): sage: K = random_cone(max_ambient_dim=3) sage: cp_gens = K.cross_positive_operators_gens() - sage: all( L.is_cross_positive_on(K) for L in cp_gens ) + sage: all(L.is_cross_positive_on(K) for L in cp_gens) True The lineality space of the cone of cross-positive operators is @@ -5994,10 +5994,10 @@ def cross_positive_operators_gens(self): sage: L = ToricLattice(K.lattice_dim()**2) sage: cp_gens = K.cross_positive_operators_gens() sage: cp_cone = Cone((g.list() for g in cp_gens), - ....: lattice=L, - ....: check=False) - sage: ll_basis = ( vector(l.list()) - ....: for l in K.lyapunov_like_basis() ) + ....: lattice=L, + ....: check=False) + sage: ll_basis = (vector(l.list()) + ....: for l in K.lyapunov_like_basis()) sage: lls = L.vector_space().span(ll_basis) sage: cp_cone.linear_subspace() == lls True @@ -6058,17 +6058,17 @@ def cross_positive_operators_gens(self): sage: K = random_cone(max_ambient_dim=3) sage: L = ToricLattice(K.lattice_dim()**2) - 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), + 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 ....: 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), + sage: expected = Cone(((p*g*p.inverse()).list() for g in cp_gens), # optional - sage.groups ....: lattice=L, ....: check=False) - sage: actual.is_equivalent(expected) + sage: actual.is_equivalent(expected) # optional - sage.groups True An operator is cross-positive on a cone if and only if its @@ -6173,7 +6173,7 @@ def Z_operators_gens(self): sage: K = random_cone(max_ambient_dim=3) sage: Z_gens = K.Z_operators_gens() - sage: all( L.is_Z_operator_on(K) for L in Z_gens ) + sage: all(L.is_Z_operator_on(K) for L in Z_gens) True """ return [ -cp for cp in self.cross_positive_operators_gens() ] @@ -6477,7 +6477,7 @@ def random_cone(lattice=None, min_ambient_dim=0, max_ambient_dim=None, It is an error to request a non-strictly-convex trivial cone:: - sage: L = ToricLattice(0,"L") + sage: L = ToricLattice(0, "L") sage: random_cone(lattice=L, strictly_convex=False) Traceback (most recent call last): ... @@ -6493,7 +6493,7 @@ def random_cone(lattice=None, min_ambient_dim=0, max_ambient_dim=None, But fine to ask for a strictly convex trivial cone:: - sage: L = ToricLattice(0,"L") + sage: L = ToricLattice(0, "L") sage: random_cone(lattice=L, strictly_convex=True) 0-d cone in 0-d lattice L diff --git a/src/sage/geometry/fan.py b/src/sage/geometry/fan.py index cd8041262a4..a3e03717da9 100644 --- a/src/sage/geometry/fan.py +++ b/src/sage/geometry/fan.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: optional - sage.graphs sage.combinat r""" Rational polyhedral fans @@ -503,12 +503,12 @@ 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() # optional - sage.plot Graphics3d Object Cones of different dimension:: - sage: c1 = Cone([(1,0),(0,1)]) + sage: c1 = Cone([(1,0), (0,1)]) sage: c2 = Cone([(2,1)]) sage: c3 = Cone([(-1,-2)]) sage: fan = Fan([c1, c2, c3], allow_arrangement=True) @@ -523,7 +523,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() # optional - sage.plot Graphics3d Object A 3-d cone and two 2-d cones:: @@ -1615,7 +1615,7 @@ def support_contains(self, *args): True sage: f.support_contains((-1,0)) False - sage: f.support_contains(f.lattice().dual()(1,0)) #random output (warning) + sage: f.support_contains(f.lattice().dual()(1,0)) # random output (warning) False sage: f.support_contains(f.lattice().dual()(1,0)) False @@ -1623,9 +1623,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)) + sage: f.support_contains(1/2, sqrt(3)) # optional - sage.symbolic True - sage: f.support_contains(-1/2, sqrt(3)) + sage: f.support_contains(-1/2, sqrt(3)) # optional - sage.symbolic False """ if len(args) == 1: @@ -1666,10 +1666,10 @@ def cartesian_product(self, other, lattice=None): EXAMPLES:: sage: K = ToricLattice(1, 'K') - sage: fan1 = Fan([[0],[1]],[(1,),(-1,)], lattice=K) + sage: fan1 = Fan([[0],[1]], [(1,),(-1,)], lattice=K) sage: L = ToricLattice(2, 'L') - sage: fan2 = Fan(rays=[(1,0),(0,1),(-1,-1)], - ....: cones=[[0,1],[1,2],[2,0]], lattice=L) + sage: fan2 = Fan(rays=[(1,0), (0,1), (-1,-1)], + ....: cones=[[0,1], [1,2], [2,0]], lattice=L) sage: fan1.cartesian_product(fan2) Rational polyhedral fan in 3-d lattice K+L sage: _.ngenerating_cones() @@ -1731,14 +1731,14 @@ def common_refinement(self, other): Refining a fan with itself gives itself:: - sage: F0 = Fan2d([(1,0),(0,1),(-1,0),(0,-1)]) + sage: F0 = Fan2d([(1,0), (0,1), (-1,0), (0,-1)]) sage: F0.common_refinement(F0) == F0 True A more complex example with complete fans:: - sage: F1 = Fan([[0],[1]],[(1,),(-1,)]) - sage: F2 = Fan2d([(1,0),(1,1),(0,1),(-1,0),(0,-1)]) + sage: F1 = Fan([[0],[1]], [(1,),(-1,)]) + sage: F2 = Fan2d([(1,0), (1,1), (0,1), (-1,0), (0,-1)]) sage: F3 = F2.cartesian_product(F1) sage: F4 = F1.cartesian_product(F2) sage: FF = F3.common_refinement(F4) @@ -1751,8 +1751,8 @@ def common_refinement(self, other): An example with two non-complete fans with the same support:: - sage: F5 = Fan2d([(1,0),(1,2),(0,1)]) - sage: F6 = Fan2d([(1,0),(2,1),(0,1)]) + sage: F5 = Fan2d([(1,0), (1,2), (0,1)]) + sage: F6 = Fan2d([(1,0), (2,1), (0,1)]) sage: F5.common_refinement(F6).ngenerating_cones() 3 @@ -1995,7 +1995,7 @@ def cone_containing(self, *points): TESTS:: sage: fan = Fan(cones=[(0,1,2,3), (0,1,4)], - ....: rays=[(1,1,1), (1,-1,1), (1,-1,-1), (1,1,-1), (0,0,1)]) + ....: rays=[(1,1,1), (1,-1,1), (1,-1,-1), (1,1,-1), (0,0,1)]) sage: fan.cone_containing(0).rays() N(1, 1, 1) in 3-d lattice N @@ -2508,18 +2508,18 @@ 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: dP8 = toric_varieties.dP8() # optional - palp sage.graphs + sage: g = dP8.fan().vertex_graph(); g # optional - palp sage.graphs 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)) # optional - palp sage.graphs True sage: g.edge_labels() # all edge labels the same since every cone is smooth # optional - palp sage.graphs [(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() # optional - sage.graphs + sage: g.automorphism_group().order() # optional - sage.graphs sage.groups 48 - sage: g.automorphism_group(edge_labels=True).order() # optional - sage.graphs sage.groups + sage: g.automorphism_group(edge_labels=True).order() # optional - sage.graphs sage.groups 4 """ from sage.geometry.cone import classify_cone_2d @@ -2680,7 +2680,7 @@ def is_isomorphic(self, other): sage: rays = ((1, 1), (0, 1), (-1, -1), (1, 0)) sage: cones = [(0,1), (1,2), (2,3), (3,0)] sage: fan1 = Fan(cones, rays) - sage: m = matrix([[-2,3],[1,-1]]) + sage: m = matrix([[-2,3], [1,-1]]) sage: fan2 = Fan(cones, [vector(r)*m for r in rays]) sage: fan1.is_isomorphic(fan2) True @@ -2782,7 +2782,7 @@ def isomorphism(self, other): sage: rays = ((1, 1), (0, 1), (-1, -1), (3, 1)) sage: cones = [(0,1), (1,2), (2,3), (3,0)] sage: fan1 = Fan(cones, rays) - sage: m = matrix([[-2,3],[1,-1]]) + sage: m = matrix([[-2,3], [1,-1]]) sage: fan2 = Fan(cones, [vector(r)*m for r in rays]) sage: fan1.isomorphism(fan2) @@ -3173,7 +3173,8 @@ def primitive_collections(self): EXAMPLES:: - sage: fan = Fan([[0,1,3],[3,4],[2,0],[1,2,4]], [(-3, -2, 1), (0, 0, 1), (3, -2, 1), (-1, -1, 1), (1, -1, 1)]) + sage: fan = Fan([[0,1,3], [3,4], [2,0], [1,2,4]], + ....: [(-3, -2, 1), (0, 0, 1), (3, -2, 1), (-1, -1, 1), (1, -1, 1)]) sage: fan.primitive_collections() [frozenset({0, 4}), frozenset({2, 3}), @@ -3233,9 +3234,11 @@ def Stanley_Reisner_ideal(self, ring): EXAMPLES:: - sage: fan = Fan([[0,1,3],[3,4],[2,0],[1,2,4]], [(-3, -2, 1), (0, 0, 1), (3, -2, 1), (-1, -1, 1), (1, -1, 1)]) - sage: fan.Stanley_Reisner_ideal( PolynomialRing(QQ,5,'A, B, C, D, E') ) - Ideal (A*E, C*D, A*B*C, B*D*E) of Multivariate Polynomial Ring in A, B, C, D, E over Rational Field + sage: fan = Fan([[0,1,3], [3,4], [2,0], [1,2,4]], + ....: [(-3, -2, 1), (0, 0, 1), (3, -2, 1), (-1, -1, 1), (1, -1, 1)]) + sage: fan.Stanley_Reisner_ideal(PolynomialRing(QQ, 5, 'A, B, C, D, E')) + Ideal (A*E, C*D, A*B*C, B*D*E) of + Multivariate Polynomial Ring in A, B, C, D, E over Rational Field """ generators_indices = self.primitive_collections() SR = ring.ideal([ prod([ ring.gen(i) for i in sr]) for sr in generators_indices ]) @@ -3257,9 +3260,11 @@ def linear_equivalence_ideal(self, ring): EXAMPLES:: - sage: fan = Fan([[0,1,3],[3,4],[2,0],[1,2,4]], [(-3, -2, 1), (0, 0, 1), (3, -2, 1), (-1, -1, 1), (1, -1, 1)]) - sage: fan.linear_equivalence_ideal( PolynomialRing(QQ,5,'A, B, C, D, E') ) - Ideal (-3*A + 3*C - D + E, -2*A - 2*C - D - E, A + B + C + D + E) of Multivariate Polynomial Ring in A, B, C, D, E over Rational Field + sage: fan = Fan([[0,1,3],[3,4],[2,0],[1,2,4]], + ....: [(-3, -2, 1), (0, 0, 1), (3, -2, 1), (-1, -1, 1), (1, -1, 1)]) + sage: fan.linear_equivalence_ideal(PolynomialRing(QQ, 5, 'A, B, C, D, E')) + Ideal (-3*A + 3*C - D + E, -2*A - 2*C - D - E, A + B + C + D + E) of + Multivariate Polynomial Ring in A, B, C, D, E over Rational Field """ gens = [] for d in range(0,self.dim()): @@ -3300,7 +3305,8 @@ def oriented_boundary(self, cone): 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 - -1-d cone of Rational polyhedral fan in 3-d lattice N + 1-d cone of Rational polyhedral fan in 3-d lattice N + -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 (-1, 1-d cone of Rational polyhedral fan in 3-d lattice N) sage: bdry[1] # optional - palp @@ -3482,22 +3488,23 @@ 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: fan = toric_varieties.P(3).fan() # optional - palp + sage: K_normal = fan.complex(); K_normal # optional - palp Chain complex with at most 4 nonzero terms over Integer Ring - sage: K_normal.homology() # optional - palp + sage: K_normal.homology() # optional - palp {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 # optional - palp Chain complex with at most 5 nonzero terms over Integer Ring - sage: K_extended.homology() # optional - palp + sage: K_extended.homology() # optional - palp {-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, base_ring=QQ) # optional - palp + sage: toric_varieties.P2_123().fan().complex(extended=True, # optional - palp + ....: base_ring=QQ) Chain complex with at most 4 nonzero terms over Rational Field - sage: _.homology() # optional - palp + sage: _.homology() # optional - 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, @@ -3525,15 +3532,15 @@ def complex(self, base_ring=ZZ, extended=False): Things get more complicated for non-complete fans:: sage: fan = Fan([Cone([(1,1,1)]), - ....: Cone([(1,0,0),(0,1,0)]), - ....: Cone([(-1,0,0),(0,-1,0),(0,0,-1)])]) + ....: Cone([(1,0,0), (0,1,0)]), + ....: Cone([(-1,0,0), (0,-1,0), (0,0,-1)])]) sage: fan.complex().homology() {0: 0, 1: 0, 2: Z x Z, 3: 0} - sage: fan = Fan([Cone([(1,0,0),(0,1,0)]), - ....: Cone([(-1,0,0),(0,-1,0),(0,0,-1)])]) + sage: fan = Fan([Cone([(1,0,0), (0,1,0)]), + ....: Cone([(-1,0,0), (0,-1,0), (0,0,-1)])]) sage: fan.complex().homology() {0: 0, 1: 0, 2: Z, 3: 0} - sage: fan = Fan([Cone([(-1,0,0),(0,-1,0),(0,0,-1)])]) + sage: fan = Fan([Cone([(-1,0,0), (0,-1,0), (0,0,-1)])]) sage: fan.complex().homology() {0: 0, 1: 0, 2: 0, 3: 0} """ diff --git a/src/sage/geometry/fan_isomorphism.py b/src/sage/geometry/fan_isomorphism.py index c3997f75b5d..0eb3b13d21c 100644 --- a/src/sage/geometry/fan_isomorphism.py +++ b/src/sage/geometry/fan_isomorphism.py @@ -216,7 +216,7 @@ 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) + sage: find_isomorphism(fan1, fan2, check=True) # optional - sage.graphs Fan morphism defined by the matrix [-2 3] [ 1 -1] diff --git a/src/sage/geometry/fan_morphism.py b/src/sage/geometry/fan_morphism.py index e94e2cce8c0..cb8105f42fc 100644 --- a/src/sage/geometry/fan_morphism.py +++ b/src/sage/geometry/fan_morphism.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.graphs, sage.combinat r""" Morphisms between toric lattices compatible with fans @@ -360,7 +361,7 @@ def _RISGIS(self): sage: normal = NormalFan(diamond) sage: N = face.lattice() sage: fm = FanMorphism(identity_matrix(2), - ....: normal, face, subdivide=True) + ....: normal, face, subdivide=True) sage: fm._RISGIS() (frozenset({2}), frozenset({3}), @@ -774,7 +775,7 @@ def _support_error(self): sage: quadrant = Fan([quadrant]) sage: quadrant_bl = quadrant.subdivide([(1,1)]) sage: fm = FanMorphism(identity_matrix(2), - ....: quadrant, quadrant_bl, check=False) + ....: quadrant, quadrant_bl, check=False) Now we report that the morphism is invalid:: @@ -861,8 +862,8 @@ def _validate(self): TESTS:: - sage: trivialfan2 = Fan([],[],lattice=ToricLattice(2)) - sage: trivialfan3 = Fan([],[],lattice=ToricLattice(3)) + sage: trivialfan2 = Fan([], [], lattice=ToricLattice(2)) + sage: trivialfan3 = Fan([], [], lattice=ToricLattice(3)) sage: FanMorphism(zero_matrix(2,3), trivialfan2, trivialfan3) Fan morphism defined by the matrix [0 0 0] @@ -983,7 +984,7 @@ def image_cone(self, cone): sage: normal = NormalFan(diamond) sage: N = face.lattice() sage: fm = FanMorphism(identity_matrix(2), - ....: normal, face, subdivide=True) + ....: normal, face, subdivide=True) sage: fm.image_cone(Cone([(1,0)])) 1-d cone of Rational polyhedral fan in 2-d lattice N sage: fm.image_cone(Cone([(1,1)])) @@ -1855,8 +1856,8 @@ def factor(self): sage: phi_i.codomain_fan() is phi.codomain_fan() # optional - palp True - sage: trivialfan2 = Fan([],[],lattice=ToricLattice(2)) - sage: trivialfan3 = Fan([],[],lattice=ToricLattice(3)) + sage: trivialfan2 = Fan([], [], lattice=ToricLattice(2)) + sage: trivialfan3 = Fan([], [], lattice=ToricLattice(3)) sage: f = FanMorphism(zero_matrix(2,3), trivialfan2, trivialfan3) sage: [phi.matrix().dimensions() for phi in f.factor()] [(0, 3), (0, 0), (2, 0)] diff --git a/src/sage/geometry/hasse_diagram.py b/src/sage/geometry/hasse_diagram.py index eeed5f560d9..f40560f30fe 100644 --- a/src/sage/geometry/hasse_diagram.py +++ b/src/sage/geometry/hasse_diagram.py @@ -104,11 +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) - sage: L + sage: L = lattice_from_incidences(atom_to_coatoms, coatom_to_atoms); L # optional - sage.graphs Finite lattice containing 8 elements with distinguished linear extension - sage: for level in L.level_sets(): print(level) + sage: for level in L.level_sets(): print(level) # optional - 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/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index b740ef79956..a9bdc1c83e4 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -60,41 +60,42 @@ The default base field is `\QQ`, the rational numbers. Finite fields are also supported:: - sage: H. = HyperplaneArrangements(GF(5)) # optional - sage.libs.pari - sage: a = H([(1,2,3), 4], [(5,6,7), 8]); a # optional - sage.libs.pari + 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 Arrangement Number fields are also possible:: - sage: x = var('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: 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 ....: [(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 # optional - sage.rings.number_field Arrangement of 5 hyperplanes of dimension 2 and rank 2 - sage: A.base_ring() # optional - sage.rings.number_field - Number Field in a with defining polynomial x^4 - 5*x^2 + 5 with a = 1.902113032590308? + sage: A.base_ring() # optional - sage.rings.number_field + 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.libs.pari - sage: k = [x+i for i in range(4)]; k # optional - sage.libs.pari + 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 [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.libs.pari + sage: H(k) # optional - sage.rings.finite_rings Arrangement Notation (iv): using the library of arrangements:: - sage: hyperplane_arrangements.braid(4) + sage: hyperplane_arrangements.braid(4) # optional - sage.graphs Arrangement of 6 hyperplanes of dimension 4 and rank 3 - sage: hyperplane_arrangements.semiorder(3) + sage: hyperplane_arrangements.semiorder(3) # optional - sage.combinat Arrangement of 6 hyperplanes of dimension 3 and rank 2 - sage: hyperplane_arrangements.graphical(graphs.PetersenGraph()) + sage: hyperplane_arrangements.graphical(graphs.PetersenGraph()) # optional - sage.graphs Arrangement of 15 hyperplanes of dimension 10 and rank 9 - sage: hyperplane_arrangements.Ish(5) + sage: hyperplane_arrangements.Ish(5) # optional - sage.combinat Arrangement of 20 hyperplanes of dimension 5 and rank 4 Notation (v): from the bounding hyperplanes of a polyhedron:: @@ -106,23 +107,23 @@ New arrangements from old:: - sage: a = hyperplane_arrangements.braid(3) - sage: b = a.add_hyperplane([4, 1, 2, 3]) - sage: b + 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 Arrangement - sage: c = b.deletion([4, 1, 2, 3]) - sage: a == c + sage: c = b.deletion([4, 1, 2, 3]) # optional - sage.graphs + sage: a == c # optional - sage.graphs True - sage: a = hyperplane_arrangements.braid(3) - sage: b = a.union(hyperplane_arrangements.semiorder(3)) - sage: b == a | hyperplane_arrangements.semiorder(3) # alternate syntax + 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 True - sage: b == hyperplane_arrangements.Catalan(3) + sage: b == hyperplane_arrangements.Catalan(3) # optional - sage.graphs sage.combinat True - - sage: a + sage: a # optional - sage.graphs sage.combinat Arrangement + sage: a = hyperplane_arrangements.coordinate(4) sage: h = a.hyperplanes()[0] sage: b = a.restriction(h) @@ -138,24 +139,24 @@ normal space (actually, it is a bit more complicated over finite fields):: - sage: a = hyperplane_arrangements.braid(4); a + sage: a = hyperplane_arrangements.braid(4); a # optional - sage.graphs Arrangement of 6 hyperplanes of dimension 4 and rank 3 - sage: a.is_essential() + sage: a.is_essential() # optional - sage.graphs False - sage: a.rank() < a.dimension() # double-check + sage: a.rank() < a.dimension() # double-check # optional - sage.graphs True - sage: a.essentialization() + sage: a.essentialization() # optional - sage.graphs 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) - sage: b = a.essentialization(); b + sage: a = hyperplane_arrangements.semiorder(3) # optional - sage.combinat + sage: b = a.essentialization(); b # optional - sage.combinat Arrangement of 6 hyperplanes of dimension 2 and rank 2 - sage: b.n_regions() + sage: b.n_regions() # optional - sage.combinat 19 - sage: b.regions() + sage: b.regions() # optional - sage.combinat (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, @@ -183,9 +184,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() + sage: b.n_bounded_regions() # optional - sage.combinat 7 - sage: a.unbounded_regions() + sage: a.unbounded_regions() # optional - sage.combinat (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, @@ -202,13 +203,13 @@ The distance between regions is defined as the number of hyperplanes separating them. For example:: - sage: r1 = b.regions()[0] - sage: r2 = b.regions()[1] - sage: b.distance_between_regions(r1, r2) + 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 1 - sage: [hyp for hyp in b if b.is_separating_hyperplane(r1, r2, hyp)] + sage: [hyp for hyp in b if b.is_separating_hyperplane(r1, r2, hyp)] # optional - sage.combinat [Hyperplane 2*t1 + t2 + 1] - sage: b.distance_enumerator(r1) # generating function for distances from r1 + sage: b.distance_enumerator(r1) # generating function for distances from r1 # optional - sage.combinat 6*x^3 + 6*x^2 + 6*x + 1 .. NOTE:: @@ -222,11 +223,11 @@ 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) - sage: p = a.intersection_poset() - sage: p.is_ranked() + sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs + sage: p = a.intersection_poset() # optional - sage.graphs + sage: p.is_ranked() # optional - sage.graphs True - sage: p.order_polytope() + sage: p.order_polytope() # optional - sage.graphs 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 @@ -262,12 +263,12 @@ Miscellaneous methods (see documentation for an explanation):: sage: a = hyperplane_arrangements.semiorder(3) - sage: a.has_good_reduction(5) + sage: a.has_good_reduction(5) # optional - sage.rings.finite_rings True - sage: b = a.change_ring(GF(5)) # optional - sage.libs.pari + sage: b = a.change_ring(GF(5)) # optional - sage.rings.finite_rings sage: pa = a.intersection_poset() - sage: pb = b.intersection_poset() # optional - sage.libs.pari - sage: pa.is_isomorphic(pb) # optional - sage.libs.pari + sage: pb = b.intersection_poset() # optional - sage.rings.finite_rings + sage: pa.is_isomorphic(pb) # optional - sage.rings.finite_rings True sage: a.face_vector() (0, 12, 30, 19) @@ -393,13 +394,13 @@ 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: 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 'normaliz' - sage: A.regions()[0].backend() # optional - pynormaliz # optional - sage.rings.number_field + sage: A.regions()[0].backend() # optional - pynormaliz sage.rings.number_field 'normaliz' """ super().__init__(parent) @@ -423,8 +424,8 @@ def _first_ngens(self, n): EXAMPLES:: - sage: a. = hyperplane_arrangements.braid(3) # indirect doctest - sage: (x, y) == a._first_ngens(2) + sage: a. = hyperplane_arrangements.braid(3) # indirect doctest # optional - sage.graphs + sage: (x, y) == a._first_ngens(2) # optional - sage.graphs True """ return self.parent()._first_ngens(n) @@ -569,14 +570,14 @@ def rank(self): sage: A.rank() 2 - sage: B = hyperplane_arrangements.braid(3) - sage: B.hyperplanes() + sage: B = hyperplane_arrangements.braid(3) # optional - sage.graphs + sage: B.hyperplanes() # optional - sage.graphs (Hyperplane 0*t0 + t1 - t2 + 0, Hyperplane t0 - t1 + 0*t2 + 0, Hyperplane t0 + 0*t1 - t2 + 0) - sage: B.dimension() + sage: B.dimension() # optional - sage.graphs 3 - sage: B.rank() + sage: B.rank() # optional - sage.graphs 2 sage: p = polytopes.simplex(5, project=True) @@ -688,7 +689,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() # optional - sage.plot Graphics object consisting of 3 graphics primitives """ from sage.geometry.hyperplane_arrangement.plot import plot @@ -719,20 +720,20 @@ def cone(self, variable='t'): EXAMPLES:: - sage: a. = hyperplane_arrangements.semiorder(3) - sage: b = a.cone() - sage: a.characteristic_polynomial().factor() + sage: a. = hyperplane_arrangements.semiorder(3) # optional - sage.combinat + sage: b = a.cone() # optional - sage.combinat + sage: a.characteristic_polynomial().factor() # optional - sage.combinat x * (x^2 - 6*x + 12) - sage: b.characteristic_polynomial().factor() + sage: b.characteristic_polynomial().factor() # optional - sage.combinat (x - 1) * x * (x^2 - 6*x + 12) - sage: a.hyperplanes() + sage: a.hyperplanes() # optional - sage.combinat (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() + sage: b.hyperplanes() # optional - sage.combinat (Hyperplane -t + 0*x + y - z + 0, Hyperplane -t + x - y + 0*z + 0, Hyperplane -t + x + 0*y - z + 0, @@ -780,21 +781,21 @@ def intersection_poset(self, element_label="int"): of hyperplanes of the arrangement. :: sage: A = hyperplane_arrangements.coordinate(2) - sage: L = A.intersection_poset(); L + sage: L = A.intersection_poset(); L # optional - sage.combinat Finite poset containing 4 elements - sage: sorted(L) + sage: sorted(L) # optional - sage.combinat [0, 1, 2, 3] - sage: L.level_sets() + sage: L.level_sets() # optional - sage.combinat [[0], [1, 2], [3]] :: - sage: A = hyperplane_arrangements.semiorder(3) - sage: L = A.intersection_poset(); L + sage: A = hyperplane_arrangements.semiorder(3) # optional - sage.combinat + sage: L = A.intersection_poset(); L # optional - sage.combinat Finite poset containing 19 elements - sage: sorted(L) + sage: sorted(L) # optional - sage.combinat [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()] + sage: [sorted(level_set) for level_set in L.level_sets()] # optional - sage.combinat [[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 @@ -802,9 +803,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) - sage: L = A.intersection_poset(element_label='subset') - sage: [sorted(level, key=sorted) for level in L.level_sets()] + 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 [[{}], [{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}]] @@ -812,31 +813,32 @@ 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') - sage: sorted(L, key=sorted) + 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 [{}, {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 + sage: L = A.intersection_poset(element_label='subspace'); L # optional - sage.combinat Finite poset containing 4 elements - sage: sorted(L, key=lambda S: (S.dimension(), S.linear_part().basis_matrix())) + sage: sorted(L, key=lambda S: (S.dimension(), # optional - sage.combinat + ....: S.linear_part().basis_matrix())) [Affine space p + W where: p = (0, 0) W = Vector space of degree 2 and dimension 0 over Rational Field - Basis matrix: - [], Affine space p + W where: + Basis matrix: [], + Affine space p + W where: p = (0, 0) W = Vector space of degree 2 and dimension 1 over Rational Field - Basis matrix: - [0 1], Affine space p + W where: + Basis matrix: [0 1], + Affine space p + W where: p = (0, 0) W = Vector space of degree 2 and dimension 1 over Rational Field - Basis matrix: - [1 0], Affine space p + W where: + Basis matrix: [1 0], + Affine space p + W where: p = (0, 0) W = Vector space of dimension 2 over Rational Field] """ @@ -903,7 +905,7 @@ def _slow_characteristic_polynomial(self): EXAMPLES:: sage: a = hyperplane_arrangements.coordinate(2) - sage: a._slow_characteristic_polynomial() + sage: a._slow_characteristic_polynomial() # optional - sage.combinat x^2 - 2*x + 1 """ from sage.rings.polynomial.polynomial_ring import polygen @@ -1016,9 +1018,9 @@ def deletion(self, hyperplanes): Checks that deletion preserves the backend:: - sage: H = HyperplaneArrangements(QQ,names='xyz') + sage: H = HyperplaneArrangements(QQ, names='xyz') sage: x,y,z = H.gens() - sage: h1,h2 = [1*x+2*y+3*z,3*x+2*y+1*z] + sage: h1,h2 = [1*x+2*y+3*z, 3*x+2*y+1*z] sage: A = H(h1,h2,backend='normaliz') sage: A.deletion(h2).backend() 'normaliz' @@ -1048,20 +1050,20 @@ def restriction(self, hyperplane): EXAMPLES:: - sage: A. = hyperplane_arrangements.braid(4); A + sage: A. = hyperplane_arrangements.braid(4); A # optional - sage.graphs Arrangement of 6 hyperplanes of dimension 4 and rank 3 - sage: H = A[0]; H + sage: H = A[0]; H # optional - sage.graphs Hyperplane 0*u + 0*x + y - z + 0 - sage: R = A.restriction(H); R + sage: R = A.restriction(H); R # optional - sage.graphs Arrangement - sage: D = A.deletion(H); D + sage: D = A.deletion(H); D # optional - sage.graphs Arrangement of 5 hyperplanes of dimension 4 and rank 3 - sage: ca = A.characteristic_polynomial() - sage: cr = R.characteristic_polynomial() - sage: cd = D.characteristic_polynomial() - sage: ca + 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 x^4 - 6*x^3 + 11*x^2 - 6*x - sage: cd - cr + sage: cd - cr # optional - sage.graphs x^4 - 6*x^3 + 11*x^2 - 6*x .. SEEALSO:: @@ -1072,9 +1074,9 @@ def restriction(self, hyperplane): Checks that restriction preserves the backend:: - sage: H = HyperplaneArrangements(QQ,names='xyz') + sage: H = HyperplaneArrangements(QQ, names='xyz') sage: x,y,z = H.gens() - sage: h1,h2 = [1*x+2*y+3*z,3*x+2*y+1*z] + sage: h1,h2 = [1*x+2*y+3*z, 3*x+2*y+1*z] sage: A = H(h1, h2, backend='normaliz') sage: A.restriction(h2).backend() 'normaliz' @@ -1128,16 +1130,16 @@ 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.libs.pari + sage: A.change_ring(FiniteField(2)) # optional - sage.rings.finite_rings Arrangement TESTS: Checks that changing the ring preserves the backend:: - sage: H = HyperplaneArrangements(QQ,names='xyz') + sage: H = HyperplaneArrangements(QQ, names='xyz') sage: x,y,z = H.gens() - sage: h1,h2 = [1*x+2*y+3*z,3*x+2*y+1*z] + sage: h1, h2 = [1*x+2*y+3*z, 3*x+2*y+1*z] sage: A = H(h1, h2, backend='normaliz') sage: A.change_ring(RDF).backend() 'normaliz' @@ -1156,16 +1158,16 @@ def n_regions(self): EXAMPLES:: - sage: A = hyperplane_arrangements.semiorder(3) - sage: A.n_regions() + sage: A = hyperplane_arrangements.semiorder(3) # optional - sage.combinat + sage: A.n_regions() # optional - sage.combinat 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.libs.pari - sage: B.n_regions() # optional - sage.libs.pari + sage: B = A.change_ring(FiniteField(7)) # optional - sage.rings.finite_rings + sage: B.n_regions() # optional - sage.rings.finite_rings Traceback (most recent call last): ... TypeError: base field must have characteristic zero @@ -1207,16 +1209,16 @@ def n_bounded_regions(self): EXAMPLES:: - sage: A = hyperplane_arrangements.semiorder(3) - sage: A.n_bounded_regions() + sage: A = hyperplane_arrangements.semiorder(3) # optional - sage.combinat + sage: A.n_bounded_regions() # optional - sage.combinat 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.libs.pari - sage: B.n_bounded_regions() # optional - sage.libs.pari + sage: B = A.change_ring(FiniteField(7)) # optional - sage.rings.finite_rings + sage: B.n_bounded_regions() # optional - sage.rings.finite_rings Traceback (most recent call last): ... TypeError: base field must have characteristic zero @@ -1246,15 +1248,15 @@ def has_good_reduction(self, p): EXAMPLES:: - sage: a = hyperplane_arrangements.semiorder(3) - sage: a.has_good_reduction(5) # optional - sage.libs.pari + sage: a = hyperplane_arrangements.semiorder(3) # optional - sage.combinat + sage: a.has_good_reduction(5) # optional - sage.combinat sage.rings.finite_rings True - sage: a.has_good_reduction(3) # optional - sage.libs.pari + sage: a.has_good_reduction(3) # optional - sage.combinat sage.rings.finite_rings False - sage: b = a.change_ring(GF(3)) # optional - sage.libs.pari - sage: a.characteristic_polynomial() + 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 x^3 - 6*x^2 + 12*x - sage: b.characteristic_polynomial() # not equal to that for a # optional - sage.libs.pari + sage: b.characteristic_polynomial() # not equal to that for a # optional - sage.combinat sage.rings.finite_rings x^3 - 6*x^2 + 10*x """ if self.base_ring() != QQ: @@ -1277,11 +1279,11 @@ def is_linear(self): EXAMPLES:: - sage: a = hyperplane_arrangements.semiorder(3) - sage: a.is_linear() + sage: a = hyperplane_arrangements.semiorder(3) # optional - sage.combinat + sage: a.is_linear() # optional - sage.combinat False - sage: b = hyperplane_arrangements.braid(3) - sage: b.is_linear() + sage: b = hyperplane_arrangements.braid(3) # optional - sage.graphs + sage: b.is_linear() # optional - sage.graphs True sage: H. = HyperplaneArrangements(QQ) @@ -1343,8 +1345,8 @@ def is_central(self, certificate=False): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(2) - sage: a.is_central() + sage: a = hyperplane_arrangements.braid(2) # optional - sage.graphs + sage: a.is_central() # optional - sage.graphs True The Catalan arrangement in dimension 3 is not central:: @@ -1355,11 +1357,11 @@ def is_central(self, certificate=False): The empty arrangement in dimension 5 is central:: - sage: H = HyperplaneArrangements(QQ,names=tuple(['x'+str(i) for i in range(7)])) + sage: H = HyperplaneArrangements(QQ, names=tuple(['x'+str(i) for i in range(7)])) sage: c = H() sage: c.is_central(certificate=True) - (True, A 7-dimensional polyhedron in QQ^7 defined as the convex - hull of 1 vertex and 7 lines) + (True, A 7-dimensional polyhedron in QQ^7 defined + as the convex hull of 1 vertex and 7 lines) """ R = self.base_ring() # If there are no hyperplanes in the arrangement, @@ -1419,15 +1421,15 @@ def center(self): The Shi arrangement in dimension 3 has an empty center:: - sage: A = hyperplane_arrangements.Shi(3) - sage: A.center() + sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat + sage: A.center() # optional - sage.combinat 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) - sage: A.center() + sage: A = hyperplane_arrangements.braid(3) # optional - sage.combinat + sage: A.center() # optional - 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] @@ -1448,16 +1450,16 @@ def is_simplicial(self): EXAMPLES:: sage: H. = HyperplaneArrangements(QQ) - sage: A = H([[0,1,1,1],[0,1,2,3]]) + sage: A = H([[0,1,1,1], [0,1,2,3]]) sage: A.is_simplicial() True - sage: A = H([[0,1,1,1],[0,1,2,3],[0,1,3,2]]) + sage: A = H([[0,1,1,1], [0,1,2,3], [0,1,3,2]]) sage: A.is_simplicial() True - sage: A = H([[0,1,1,1],[0,1,2,3],[0,1,3,2],[0,2,1,3]]) + 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() + sage: hyperplane_arrangements.braid(3).is_simplicial() # optional - sage.graphs True """ # if the arr is not essential, grab the essential version and check there. @@ -1483,10 +1485,10 @@ def essentialization(self): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(3) - sage: a.is_essential() + sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs + sage: a.is_essential() # optional - sage.graphs False - sage: a.essentialization() + sage: a.essentialization() # optional - sage.graphs Arrangement sage: H. = HyperplaneArrangements(QQ) @@ -1499,13 +1501,13 @@ def essentialization(self): Hyperplane arrangements in 1-dimensional linear space over Rational Field with coordinate x - sage: H. = HyperplaneArrangements(GF(2)) # optional - sage.libs.pari - sage: C = H([(1,1),1], [(1,1),0]) # optional - sage.libs.pari - sage: C.essentialization() # optional - sage.libs.pari + 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 Arrangement - sage: h = hyperplane_arrangements.semiorder(4) - sage: h.essentialization() + sage: h = hyperplane_arrangements.semiorder(4) # optional - sage.combinat + sage: h.essentialization() # optional - sage.combinat Arrangement of 12 hyperplanes of dimension 3 and rank 3 TESTS:: @@ -1591,9 +1593,9 @@ def sign_vector(self, p): TESTS:: - sage: H. = HyperplaneArrangements(GF(3)) # optional - sage.libs.pari - sage: A = H(x, y) # optional - sage.libs.pari - sage: A.sign_vector([1, 2]) # optional - sage.libs.pari + 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 Traceback (most recent call last): ... ValueError: characteristic must be zero @@ -1620,8 +1622,8 @@ def face_vector(self): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3) - sage: A.face_vector() + sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat + sage: A.face_vector() # optional - sage.combinat (0, 6, 21, 16) """ m = self.whitney_data()[0] @@ -1660,7 +1662,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() + sage: hyperplane_arrangements.Shi(3)._parallel_hyperplanes() # optional - sage.combinat (((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), @@ -1703,21 +1705,21 @@ def vertices(self, exclude_sandwiched=False): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3).essentialization() - sage: A.dimension() + sage: A = hyperplane_arrangements.Shi(3).essentialization() # optional - sage.combinat + sage: A.dimension() # optional - sage.combinat 2 - sage: A.face_vector() + sage: A.face_vector() # optional - sage.combinat (6, 21, 16) - sage: A.vertices() + sage: A.vertices() # optional - sage.combinat ((-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.plot + sage: point2d(A.vertices(), size=20) + A.plot() # optional - sage.combinat sage.plot Graphics object consisting of 7 graphics primitives sage: H. = HyperplaneArrangements(QQ) sage: chessboard = [] sage: N = 8 - sage: for x0 in range(N+1): - ....: for y0 in range(N+1): + sage: for x0 in range(N + 1): + ....: for y0 in range(N + 1): ....: chessboard.extend([x-x0, y-y0]) sage: chessboard = H(chessboard) sage: len(chessboard.vertices()) @@ -1780,8 +1782,8 @@ 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._make_region([x, 1-x, y, 1-y]).backend() # optional - pynormaliz + sage: h = H(x,backend='normaliz') # optional - pynormaliz + sage: h._make_region([x, 1-x, y, 1-y]).backend() # optional - pynormaliz 'normaliz' """ ieqs = [h.dense_coefficient_list() for h in hyperplanes] @@ -1806,23 +1808,29 @@ def regions(self): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(2) - sage: a.regions() - (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: a = hyperplane_arrangements.braid(2) # optional - sage.graphs + sage: a.regions() # optional - 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 + as the convex hull of 1 vertex, 1 ray, 1 line) sage: H. = HyperplaneArrangements(QQ) sage: A = H(x, y+1) sage: A.regions() - (A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays, - A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays, - A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays, - A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays) + (A 2-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 2 rays, + A 2-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 2 rays, + A 2-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 2 rays, + A 2-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 2 rays) sage: chessboard = [] sage: N = 8 - sage: for x0 in range(N+1): - ....: for y0 in range(N+1): + sage: for x0 in range(N + 1): + ....: for y0 in range(N + 1): ....: chessboard.extend([x-x0, y-y0]) sage: chessboard = H(chessboard) sage: len(chessboard.bounded_regions()) # long time, 359 ms on a Core i7 @@ -1855,20 +1863,21 @@ def regions(self): It is possible to specify the backend:: - 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], - ....: [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) - sage: A = H(backend='normaliz') - sage: for v in norms: + sage: K. = CyclotomicField(9) # optional - sage.rings.number_field + sage: L. = NumberField((q + q**(-1)).minpoly(), # optional - sage.rings.number_field + ....: embedding=AA(q + q**-1)) + sage: norms = [[1, 1/3*(-2*r9**2-r9+1), 0], # optional - sage.rings.number_field + ....: [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 ....: a,b,c = v ....: A = A.add_hyperplane(a*x + b*y + c*z) - sage: R = A.regions() # optional - pynormaliz - sage: R[0].backend() # optional - pynormaliz + sage: R = A.regions() # optional - pynormaliz sage.rings.number_field + sage: R[0].backend() # optional - pynormaliz sage.rings.number_field 'normaliz' TESTS:: @@ -1876,7 +1885,8 @@ def regions(self): sage: K. = HyperplaneArrangements(QQ) sage: A = K() sage: A.regions() - (A 5-dimensional polyhedron in QQ^5 defined as the convex hull of 1 vertex and 5 lines,) + (A 5-dimensional polyhedron in QQ^5 + defined as the convex hull of 1 vertex and 5 lines,) """ if self.base_ring().characteristic() != 0: raise ValueError('base field must have characteristic zero') @@ -1976,24 +1986,24 @@ def poset_of_regions(self, B=None, numbered_labels=True): EXAMPLES:: sage: H. = HyperplaneArrangements(QQ) - sage: A = H([[0,1,1,1],[0,1,2,3]]) - sage: A.poset_of_regions() + sage: A = H([[0,1,1,1], [0,1,2,3]]) + sage: A.poset_of_regions() # optional - sage.combinat Finite poset containing 4 elements - sage: A = hyperplane_arrangements.braid(3) - sage: A.poset_of_regions() + sage: A = hyperplane_arrangements.braid(3) # optional - sage.combinat sage.graphs + sage: A.poset_of_regions() # optional - sage.combinat sage.graphs Finite poset containing 6 elements - sage: A.poset_of_regions(numbered_labels=False) + sage: A.poset_of_regions(numbered_labels=False) # optional - sage.combinat sage.graphs Finite poset containing 6 elements - sage: A = hyperplane_arrangements.braid(4) - sage: A.poset_of_regions() + sage: A = hyperplane_arrangements.braid(4) # optional - sage.combinat sage.graphs + sage: A.poset_of_regions() # optional - sage.combinat sage.graphs 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() - sage: base_region = R[3] - sage: A.poset_of_regions(B=base_region) + 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 Finite poset containing 14 elements """ from sage.combinat.posets.posets import Poset @@ -2098,109 +2108,87 @@ def closed_faces(self, labelled=True): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(2) - sage: a.hyperplanes() + sage: a = hyperplane_arrangements.braid(2) # optional - sage.graphs + sage: a.hyperplanes() # optional - sage.graphs (Hyperplane t0 - t1 + 0,) - 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) - (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()] - [((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 as the convex hull of 1 vertex, 1 ray, 1 line, - (0, -1)), - ((-1,), - A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, 1 ray, 1 line, - (-1, 0))] + sage: a.closed_faces() # optional - sage.graphs + (((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 + (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 + [((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 + as the convex hull of 1 vertex, 1 ray, 1 line, (0, -1)), + ((-1,), A 2-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex, 1 ray, 1 line, (-1, 0))] sage: H. = HyperplaneArrangements(QQ) sage: a = H(x, y+1) sage: a.hyperplanes() (Hyperplane 0*x + y + 1, Hyperplane x + 0*y + 0) sage: [(v, F, F.representative_point()) for v, F in a.closed_faces()] - [((0, 0), - A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex, - (0, -1)), - ((0, 1), - A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 ray, - (1, -1)), - ((0, -1), - A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 ray, - (-1, -1)), - ((1, 0), - A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 ray, - (0, 0)), - ((1, 1), - A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays, - (1, 0)), - ((1, -1), - A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays, - (-1, 0)), - ((-1, 0), - A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 ray, - (0, -2)), - ((-1, 1), - A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays, - (1, -2)), - ((-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) - sage: a.hyperplanes() + [((0, 0), A 0-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex, (0, -1)), + ((0, 1), A 1-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 1 ray, (1, -1)), + ((0, -1), A 1-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 1 ray, (-1, -1)), + ((1, 0), A 1-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 1 ray, (0, 0)), + ((1, 1), A 2-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 2 rays, (1, 0)), + ((1, -1), A 2-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 2 rays, (-1, 0)), + ((-1, 0), A 1-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 1 ray, (0, -2)), + ((-1, 1), A 2-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 2 rays, (1, -2)), + ((-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 (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()] - [((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 as the convex hull of 1 vertex, 1 ray, 1 line, - (0, -1, -1)), - ((0, -1, -1), - A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 1 ray, 1 line, - (-1, 0, 0)), - ((1, 0, 1), - A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 1 ray, 1 line, - (1, 1, 0)), - ((1, 1, 1), - A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line, - (0, -1, -2)), - ((1, -1, 0), - A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 1 ray, 1 line, - (-1, 0, -1)), - ((1, -1, 1), - A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line, - (1, 2, 0)), - ((1, -1, -1), - A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line, - (-2, 0, -1)), - ((-1, 0, -1), - A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 1 ray, 1 line, - (0, 0, 1)), - ((-1, 1, 0), - A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 1 ray, 1 line, - (1, 0, 1)), - ((-1, 1, 1), - A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line, - (0, -2, -1)), - ((-1, 1, -1), - A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line, - (1, 0, 2)), - ((-1, -1, -1), - A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line, - (-1, 0, 1))] + sage: [(v, F, F.representative_point()) for v, F in a.closed_faces()] # optional - 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 + as the convex hull of 1 vertex, 1 ray, 1 line, (0, -1, -1)), + ((0, -1, -1), A 2-dimensional polyhedron in QQ^3 defined + as the convex hull of 1 vertex, 1 ray, 1 line, (-1, 0, 0)), + ((1, 0, 1), A 2-dimensional polyhedron in QQ^3 defined + as the convex hull of 1 vertex, 1 ray, 1 line, (1, 1, 0)), + ((1, 1, 1), A 3-dimensional polyhedron in QQ^3 defined + as the convex hull of 1 vertex, 2 rays, 1 line, (0, -1, -2)), + ((1, -1, 0), A 2-dimensional polyhedron in QQ^3 defined + as the convex hull of 1 vertex, 1 ray, 1 line, (-1, 0, -1)), + ((1, -1, 1), A 3-dimensional polyhedron in QQ^3 defined + as the convex hull of 1 vertex, 2 rays, 1 line, (1, 2, 0)), + ((1, -1, -1), A 3-dimensional polyhedron in QQ^3 defined + as the convex hull of 1 vertex, 2 rays, 1 line, (-2, 0, -1)), + ((-1, 0, -1), A 2-dimensional polyhedron in QQ^3 defined + as the convex hull of 1 vertex, 1 ray, 1 line, (0, 0, 1)), + ((-1, 1, 0), A 2-dimensional polyhedron in QQ^3 defined + as the convex hull of 1 vertex, 1 ray, 1 line, (1, 0, 1)), + ((-1, 1, 1), A 3-dimensional polyhedron in QQ^3 defined + as the convex hull of 1 vertex, 2 rays, 1 line, (0, -2, -1)), + ((-1, 1, -1), A 3-dimensional polyhedron in QQ^3 defined + as the convex hull of 1 vertex, 2 rays, 1 line, (1, 0, 2)), + ((-1, -1, -1), A 3-dimensional polyhedron in QQ^3 defined + as the convex hull of 1 vertex, 2 rays, 1 line, (-1, 0, 1))] Let us check that the number of closed faces with a given dimension computed using ``self.closed_faces()`` equals the one @@ -2212,10 +2200,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) + sage: test_number(a) # optional - sage.combinat True - sage: a = hyperplane_arrangements.Shi(3) - sage: test_number(a) # long time + sage: a = hyperplane_arrangements.Shi(3) # optional - sage.combinat + sage: test_number(a) # long time # optional - sage.combinat True TESTS: @@ -2350,27 +2338,27 @@ def face_product(self, F, G, normalize=True): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(3) - sage: a.hyperplanes() + sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs + sage: a.hyperplanes() # optional - sage.graphs (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()} - sage: xGyEz = faces[(0, 1, 1)] # closed face x >= y = z - sage: xGyEz.representative_point() + 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 (0, -1, -1) - sage: xGyEz = faces[(0, 1, 1)] # closed face x >= y = z - sage: xGyEz.representative_point() + sage: xGyEz = faces[(0, 1, 1)] # closed face x >= y = z # optional - sage.graphs + sage: xGyEz.representative_point() # optional - sage.graphs (0, -1, -1) - 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 + 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 True - sage: a.face_product(yGxGz, xGyEz) == yGxGz + sage: a.face_product(yGxGz, xGyEz) == yGxGz # optional - sage.graphs True - 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 + 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 True """ f = F.representative_point() @@ -2445,8 +2433,8 @@ def face_semigroup_algebra(self, field=None, names='e'): EXAMPLES:: - sage: a = hyperplane_arrangements.braid(3) - sage: [(i, F[0]) for i, F in enumerate(a.closed_faces())] + sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs + sage: [(i, F[0]) for i, F in enumerate(a.closed_faces())] # optional - sage.graphs [(0, (0, 0, 0)), (1, (0, 1, 1)), (2, (0, -1, -1)), @@ -2460,44 +2448,44 @@ 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 + sage: U = a.face_semigroup_algebra(); U # optional - sage.graphs 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() - sage: e0 * e1 + 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 e1 - sage: e0 * e5 + sage: e0 * e5 # optional - sage.graphs e5 - sage: e5 * e0 + sage: e5 * e0 # optional - sage.graphs e5 - sage: e3 * e2 + sage: e3 * e2 # optional - sage.graphs e6 - sage: e7 * e12 + sage: e7 * e12 # optional - sage.graphs e7 - sage: e3 * e12 + sage: e3 * e12 # optional - sage.graphs e6 - sage: e4 * e8 + sage: e4 * e8 # optional - sage.graphs e4 - sage: e8 * e4 + sage: e8 * e4 # optional - sage.graphs e11 - sage: e8 * e1 + sage: e8 * e1 # optional - sage.graphs e11 - sage: e5 * e12 + sage: e5 * e12 # optional - sage.graphs e7 - sage: (e3 + 2*e4) * (e1 - e7) + sage: (e3 + 2*e4) * (e1 - e7) # optional - sage.graphs e4 - e6 - sage: U3 = a.face_semigroup_algebra(field=GF(3)); U3 # optional - sage.libs.pari + sage: U3 = a.face_semigroup_algebra(field=GF(3)); U3 # optional - 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) - sage: U = a.face_semigroup_algebra(names='x'); U + sage: a = hyperplane_arrangements.braid(3) # optional - sage.graphs + sage: U = a.face_semigroup_algebra(names='x'); U # optional - sage.graphs 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() - sage: e0 * e1 + 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 x1 """ if field is None: @@ -2551,13 +2539,14 @@ def region_containing_point(self, p): sage: H. = HyperplaneArrangements(QQ) sage: A = H([(1,0), 0], [(0,1), 1], [(0,1), -1], [(1,-1), 0], [(1,1), 0]) sage: A.region_containing_point([1,2]) - A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 2 rays + A 2-dimensional polyhedron in QQ^2 defined + as the convex hull of 2 vertices and 2 rays TESTS:: sage: A = H([(1,1),0], [(2,3),-1], [(4,5),3]) - sage: B = A.change_ring(FiniteField(7)) # optional - sage.libs.pari - sage: B.region_containing_point((1,2)) # optional - sage.libs.pari + sage: B = A.change_ring(FiniteField(7)) # optional - sage.rings.finite_rings + sage: B.region_containing_point((1,2)) # optional - sage.rings.finite_rings Traceback (most recent call last): ... ValueError: base field must have characteristic zero @@ -2595,8 +2584,8 @@ def _bounded_region_indices(self): EXAMPLES:: - sage: a = hyperplane_arrangements.semiorder(3) - sage: a._bounded_region_indices() + sage: a = hyperplane_arrangements.semiorder(3) # optional - sage.combinat + sage: a._bounded_region_indices() # optional - sage.combinat (2, 7, 8, 9, 10, 11, 16) """ from sage.geometry.polyhedron.constructor import Polyhedron @@ -2631,18 +2620,25 @@ def bounded_regions(self): EXAMPLES:: - 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 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, - A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 6 vertices and 1 line, - 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 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 + sage: A = hyperplane_arrangements.semiorder(3) # optional - sage.combinat + sage: A.bounded_regions() # optional - sage.combinat + (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 + 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, + A 3-dimensional polyhedron in QQ^3 defined + as the convex hull of 6 vertices and 1 line, + 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 + 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 False - sage: A.is_essential() + sage: A.is_essential() # optional - sage.combinat False """ return tuple(self.regions()[i] for i in self._bounded_region_indices()) @@ -2663,23 +2659,35 @@ def unbounded_regions(self): EXAMPLES:: - sage: A = hyperplane_arrangements.semiorder(3) - sage: B = A.essentialization() - sage: B.n_regions() - B.n_bounded_regions() + 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 12 - 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 as the convex hull of 3 vertices and 1 ray, - A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays, - 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 as the convex hull of 1 vertex and 2 rays, - 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 as the convex hull of 1 vertex and 2 rays, - 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 as the convex hull of 1 vertex and 2 rays, - 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 as the convex hull of 1 vertex and 2 rays, - A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays) + sage: B.unbounded_regions() # optional - sage.combinat + (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 + as the convex hull of 3 vertices and 1 ray, + A 2-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 2 rays, + 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 + as the convex hull of 1 vertex and 2 rays, + 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 + as the convex hull of 1 vertex and 2 rays, + 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 + as the convex hull of 1 vertex and 2 rays, + 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 + as the convex hull of 1 vertex and 2 rays, + A 2-dimensional polyhedron in QQ^2 defined + as the convex hull of 1 vertex and 2 rays) """ s = set(range(self.n_regions())).difference(set(self._bounded_region_indices())) return tuple(self.regions()[i] for i in s) @@ -2703,8 +2711,8 @@ def whitney_data(self): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3) - sage: A.whitney_data() + sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat + sage: A.whitney_data() # optional - sage.combinat ( [ 1 -6 9] [ 1 6 6] [ 0 6 -15] [ 0 6 15] @@ -2753,12 +2761,12 @@ def doubly_indexed_whitney_number(self, i, j, kind=1): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3) - sage: A.doubly_indexed_whitney_number(0, 2) + sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat + sage: A.doubly_indexed_whitney_number(0, 2) # optional - sage.combinat 9 - sage: A.whitney_number(2) + sage: A.whitney_number(2) # optional - sage.combinat 9 - sage: A.doubly_indexed_whitney_number(1, 2) + sage: A.doubly_indexed_whitney_number(1, 2) # optional - sage.combinat -15 REFERENCES: @@ -2803,20 +2811,20 @@ def whitney_number(self, k, kind=1): EXAMPLES:: - sage: A = hyperplane_arrangements.Shi(3) - sage: A.whitney_number(0) + sage: A = hyperplane_arrangements.Shi(3) # optional - sage.combinat + sage: A.whitney_number(0) # optional - sage.combinat 1 - sage: A.whitney_number(1) + sage: A.whitney_number(1) # optional - sage.combinat -6 - sage: A.whitney_number(2) + sage: A.whitney_number(2) # optional - sage.combinat 9 - sage: A.characteristic_polynomial() + sage: A.characteristic_polynomial() # optional - sage.combinat x^3 - 6*x^2 + 9*x - sage: A.whitney_number(1,kind=2) + sage: A.whitney_number(1, kind=2) # optional - sage.combinat 6 - sage: p = A.intersection_poset() - sage: r = p.rank_function() - sage: len([i for i in p if r(i) == 1]) + 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 6 """ if k >= 0 and k <= self.dimension(): @@ -2996,7 +3004,7 @@ def matroid(self): We check the lattice of flats is isomorphic to the intersection lattice:: - sage: f = sum([list(M.flats(i)) for i in range(M.rank()+1)], []) + 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 True @@ -3088,13 +3096,13 @@ def minimal_generated_number(self): Check that :trac:`26705` is fixed:: - sage: w = WeylGroup(['A',4]).from_reduced_word([3,4,2,1]) - sage: I = w.inversion_arrangement() - sage: I + 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 Arrangement - sage: I.minimal_generated_number() + sage: I.minimal_generated_number() # optional - sage.combinat sage.groups 0 - sage: I.is_formal() + sage: I.is_formal() # optional - sage.combinat sage.groups True """ V = VectorSpace(self.base_ring(), self.dimension()) @@ -3176,9 +3184,9 @@ def derivation_module_free_chain(self): EXAMPLES:: - sage: W = WeylGroup(['A',3], prefix='s') - sage: A = W.long_element().inversion_arrangement() - sage: for M in A.derivation_module_free_chain(): print("%s\n"%M) + 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 [ 1 0 0] [ 0 1 0] [ 0 0 a3] @@ -3252,8 +3260,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') - sage: for x in W: + sage: W = WeylGroup(['A', 3], prefix='s') # optional - sage.combinat sage.groups + sage: for x in W: # optional - sage.combinat sage.groups ....: A = x.inversion_arrangement() ....: assert A.matroid().is_chordal() == A.is_free() @@ -3261,8 +3269,8 @@ def is_free(self, algorithm="singular"): We check that the algorithms agree:: - sage: W = WeylGroup(['B',3], prefix='s') - sage: for x in W: # long time + sage: W = WeylGroup(['B', 3], prefix='s') # optional - sage.combinat sage.groups + sage: for x in W: # long time # optional - sage.combinat sage.groups ....: A = x.inversion_arrangement() ....: assert (A.is_free(algorithm="BC") ....: == A.is_free(algorithm="singular")) @@ -3321,19 +3329,19 @@ def derivation_module_basis(self, algorithm="singular"): EXAMPLES:: - sage: W = WeylGroup(['A',2], prefix='s') - sage: A = W.long_element().inversion_arrangement() - sage: A.derivation_module_basis() + 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 [(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') - sage: exponents = lambda B: sorted([max(x.degree() for x in b) - ....: for b in B]) - sage: for x in W: # long time + sage: W = WeylGroup(['A', 2], prefix='s') # optional - sage.combinat sage.groups + sage: def exponents(B): # optional - sage.combinat sage.groups + ....: 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 ....: A = x.inversion_arrangement() ....: B = A.derivation_module_basis(algorithm="singular") ....: Bp = A.derivation_module_basis(algorithm="BC") @@ -3665,7 +3673,8 @@ def gen(self, i): 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.gen(0) Hyperplane x + 0*y + 0*z + 0 """ diff --git a/src/sage/geometry/hyperplane_arrangement/check_freeness.py b/src/sage/geometry/hyperplane_arrangement/check_freeness.py index 30f963612ec..e99c8ee9b39 100644 --- a/src/sage/geometry/hyperplane_arrangement/check_freeness.py +++ b/src/sage/geometry/hyperplane_arrangement/check_freeness.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.libs.singular r""" Helper Functions For Freeness Of Hyperplane Arrangements diff --git a/src/sage/geometry/hyperplane_arrangement/hyperplane.py b/src/sage/geometry/hyperplane_arrangement/hyperplane.py index c431291a3a6..8284022d3d8 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)) + sage: h.change_ring(GF(3)) # optional - sage.rings.finite_rings 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)) - sage: V = H.ambient_space() - sage: (x + 3*y - 4*z)._normal_pivot() + 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 1 """ try: @@ -397,16 +397,16 @@ def point(self): sage: h.point() in h True - sage: H. = HyperplaneArrangements(GF(3)) - sage: h = 2*x + y + z + 1 - sage: h.point() + 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 (1, 0, 0) - sage: h.point().base_ring() + sage: h.point().base_ring() # optional - sage.rings.finite_rings Finite Field of size 3 - sage: H. = HyperplaneArrangements(GF(3)) - sage: h = x + y + z + 1 - sage: h.point() + 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 (2, 0, 0) """ P = self.parent() @@ -552,21 +552,21 @@ def primitive(self, signed=True): Check that :trac:`30078` is fixed:: - sage: R. = QuadraticField(2) - sage: H. = HyperplaneArrangements(base_ring=R) - sage: B = H([1,1,0], [2,2,0], [sqrt2,sqrt2,0]) - sage: B + 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 Arrangement Check that :trac:`30749` is fixed:: - 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() + 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 60 """ from sage.rings.rational_field import QQ @@ -638,7 +638,7 @@ def plot(self, **kwds): EXAMPLES:: sage: L. = HyperplaneArrangements(QQ) - sage: (x+y-2).plot() # optional - sage.plot + sage: (x + y - 2).plot() # optional - 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 37da03eda7c..4dc33701b56 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) + sage: hyperplane_arrangements.braid(4) # optional - sage.graphs Arrangement of 6 hyperplanes of dimension 4 and rank 3 """ x = polygen(QQ, 'x') @@ -124,18 +124,18 @@ def bigraphical(self, G, A=None, K=QQ, names=None): EXAMPLES:: - sage: G = graphs.CycleGraph(4) - sage: G.edges(sort=True) + sage: G = graphs.CycleGraph(4) # optional - sage.graphs + sage: G.edges(sort=True) # optional - sage.graphs [(0, 1, None), (0, 3, None), (1, 2, None), (2, 3, None)] - sage: G.edges(sort=True, labels=False) + sage: G.edges(sort=True, labels=False) # optional - sage.graphs [(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}} - sage: HA = hyperplane_arrangements.bigraphical(G, A) - sage: HA.n_regions() + 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 63 - sage: hyperplane_arrangements.bigraphical(G, 'generic').n_regions() + sage: hyperplane_arrangements.bigraphical(G, 'generic').n_regions() # optional - sage.graphs 65 - sage: hyperplane_arrangements.bigraphical(G).n_regions() + sage: hyperplane_arrangements.bigraphical(G).n_regions() # optional - sage.graphs 59 REFERENCES: @@ -253,11 +253,11 @@ def G_semiorder(self, G, K=QQ, names=None): EXAMPLES:: - sage: G = graphs.CompleteGraph(5) - sage: hyperplane_arrangements.G_semiorder(G) + sage: G = graphs.CompleteGraph(5) # optional - sage.graphs + sage: hyperplane_arrangements.G_semiorder(G) # optional - sage.graphs Arrangement of 20 hyperplanes of dimension 5 and rank 4 - sage: g = graphs.HouseGraph() - sage: hyperplane_arrangements.G_semiorder(g) + sage: g = graphs.HouseGraph() # optional - sage.graphs + sage: hyperplane_arrangements.G_semiorder(g) # optional - sage.graphs Arrangement of 12 hyperplanes of dimension 5 and rank 4 """ n = G.num_verts() @@ -291,13 +291,13 @@ def G_Shi(self, G, K=QQ, names=None): EXAMPLES:: - sage: G = graphs.CompleteGraph(5) - sage: hyperplane_arrangements.G_Shi(G) + sage: G = graphs.CompleteGraph(5) # optional - sage.graphs + sage: hyperplane_arrangements.G_Shi(G) # optional - sage.graphs Arrangement of 20 hyperplanes of dimension 5 and rank 4 - sage: g = graphs.HouseGraph() - sage: hyperplane_arrangements.G_Shi(g) + sage: g = graphs.HouseGraph() # optional - sage.graphs + sage: hyperplane_arrangements.G_Shi(g) # optional - sage.graphs Arrangement of 12 hyperplanes of dimension 5 and rank 4 - sage: a = hyperplane_arrangements.G_Shi(graphs.WheelGraph(4)); a + sage: a = hyperplane_arrangements.G_Shi(graphs.WheelGraph(4)); a # optional - sage.graphs Arrangement of 12 hyperplanes of dimension 4 and rank 3 """ n = G.num_verts() @@ -333,20 +333,20 @@ def graphical(self, G, K=QQ, names=None): EXAMPLES:: - sage: G = graphs.CompleteGraph(5) - sage: hyperplane_arrangements.graphical(G) + sage: G = graphs.CompleteGraph(5) # optional - sage.graphs + sage: hyperplane_arrangements.graphical(G) # optional - sage.graphs Arrangement of 10 hyperplanes of dimension 5 and rank 4 - sage: g = graphs.HouseGraph() - sage: hyperplane_arrangements.graphical(g) + sage: g = graphs.HouseGraph() # optional - sage.graphs + sage: hyperplane_arrangements.graphical(g) # optional - sage.graphs Arrangement of 6 hyperplanes of dimension 5 and rank 4 TESTS:: - sage: h = hyperplane_arrangements.graphical(g) - sage: h.characteristic_polynomial() + sage: h = hyperplane_arrangements.graphical(g) # optional - sage.graphs + sage: h.characteristic_polynomial() # optional - sage.graphs x^5 - 6*x^4 + 14*x^3 - 15*x^2 + 6*x - sage: h.characteristic_polynomial.clear_cache() # long time - sage: h.characteristic_polynomial() # long time + sage: h.characteristic_polynomial.clear_cache() # long time # optional - sage.graphs + sage: h.characteristic_polynomial() # long time # optional - sage.graphs x^5 - 6*x^4 + 14*x^3 - 15*x^2 + 6*x """ n = G.num_verts() @@ -388,18 +388,18 @@ def Ish(self, n, K=QQ, names=None): EXAMPLES:: - sage: a = hyperplane_arrangements.Ish(3); a + sage: a = hyperplane_arrangements.Ish(3); a # optional - sage.combinat Arrangement of 6 hyperplanes of dimension 3 and rank 2 - sage: a.characteristic_polynomial() + sage: a.characteristic_polynomial() # optional - sage.combinat x^3 - 6*x^2 + 9*x - sage: b = hyperplane_arrangements.Shi(3) - sage: b.characteristic_polynomial() + sage: b = hyperplane_arrangements.Shi(3) # optional - sage.combinat + sage: b.characteristic_polynomial() # optional - sage.combinat x^3 - 6*x^2 + 9*x TESTS:: - sage: a.characteristic_polynomial.clear_cache() # long time - sage: a.characteristic_polynomial() # long time + sage: a.characteristic_polynomial.clear_cache() # long time # optional - sage.combinat + sage: a.characteristic_polynomial() # long time # optional - sage.combinat x^3 - 6*x^2 + 9*x REFERENCES: @@ -486,16 +486,16 @@ def semiorder(self, n, K=QQ, names=None): EXAMPLES:: - sage: hyperplane_arrangements.semiorder(4) + sage: hyperplane_arrangements.semiorder(4) # optional - sage.combinat Arrangement of 12 hyperplanes of dimension 4 and rank 3 TESTS:: - sage: h = hyperplane_arrangements.semiorder(5) - sage: h.characteristic_polynomial() + sage: h = hyperplane_arrangements.semiorder(5) # optional - sage.combinat + sage: h.characteristic_polynomial() # optional - sage.combinat x^5 - 20*x^4 + 180*x^3 - 790*x^2 + 1380*x - sage: h.characteristic_polynomial.clear_cache() # long time - sage: h.characteristic_polynomial() # long time + sage: h.characteristic_polynomial.clear_cache() # long time # optional - sage.combinat + sage: h.characteristic_polynomial() # long time # optional - sage.combinat x^5 - 20*x^4 + 180*x^3 - 790*x^2 + 1380*x """ H = make_parent(K, n, names) @@ -547,29 +547,29 @@ def Shi(self, data, K=QQ, names=None, m=1): EXAMPLES:: - sage: hyperplane_arrangements.Shi(4) + sage: hyperplane_arrangements.Shi(4) # optional - sage.combinat Arrangement of 12 hyperplanes of dimension 4 and rank 3 - sage: hyperplane_arrangements.Shi("A3") + sage: hyperplane_arrangements.Shi("A3") # optional - sage.combinat Arrangement of 12 hyperplanes of dimension 4 and rank 3 - sage: hyperplane_arrangements.Shi("A3",m=2) + sage: hyperplane_arrangements.Shi("A3", m=2) # optional - sage.combinat Arrangement of 24 hyperplanes of dimension 4 and rank 3 - sage: hyperplane_arrangements.Shi("B4") + sage: hyperplane_arrangements.Shi("B4") # optional - sage.combinat Arrangement of 32 hyperplanes of dimension 4 and rank 4 - sage: hyperplane_arrangements.Shi("B4",m=3) + sage: hyperplane_arrangements.Shi("B4", m=3) # optional - sage.combinat Arrangement of 96 hyperplanes of dimension 4 and rank 4 - sage: hyperplane_arrangements.Shi("C3") + sage: hyperplane_arrangements.Shi("C3") # optional - sage.combinat Arrangement of 18 hyperplanes of dimension 3 and rank 3 - sage: hyperplane_arrangements.Shi("D4",m=3) + sage: hyperplane_arrangements.Shi("D4", m=3) # optional - sage.combinat Arrangement of 72 hyperplanes of dimension 4 and rank 4 - sage: hyperplane_arrangements.Shi("E6") + sage: hyperplane_arrangements.Shi("E6") # optional - sage.combinat Arrangement of 72 hyperplanes of dimension 8 and rank 6 - sage: hyperplane_arrangements.Shi("E6",m=2) + sage: hyperplane_arrangements.Shi("E6", m=2) # optional - sage.combinat 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") + sage: hyperplane_arrangements.Shi("H4") # optional - sage.combinat Traceback (most recent call last): ... NotImplementedError: Shi arrangements are not defined for non crystallographic Cartan types @@ -577,36 +577,36 @@ 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() + sage: hyperplane_arrangements.Shi("A3").characteristic_polynomial() # optional - sage.combinat x^4 - 12*x^3 + 48*x^2 - 64*x - sage: hyperplane_arrangements.Shi("A3",m=2).characteristic_polynomial() + sage: hyperplane_arrangements.Shi("A3", m=2).characteristic_polynomial() # optional - sage.combinat x^4 - 24*x^3 + 192*x^2 - 512*x - sage: hyperplane_arrangements.Shi("C3").characteristic_polynomial() + sage: hyperplane_arrangements.Shi("C3").characteristic_polynomial() # optional - sage.combinat x^3 - 18*x^2 + 108*x - 216 - sage: hyperplane_arrangements.Shi("E6").characteristic_polynomial() + sage: hyperplane_arrangements.Shi("E6").characteristic_polynomial() # optional - sage.combinat 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() + sage: hyperplane_arrangements.Shi("B4", m=3).characteristic_polynomial() # optional - sage.combinat x^4 - 96*x^3 + 3456*x^2 - 55296*x + 331776 TESTS:: - sage: h = hyperplane_arrangements.Shi(4) - sage: h.characteristic_polynomial() + sage: h = hyperplane_arrangements.Shi(4) # optional - sage.combinat + sage: h.characteristic_polynomial() # optional - sage.combinat x^4 - 12*x^3 + 48*x^2 - 64*x - sage: h.characteristic_polynomial.clear_cache() # long time - sage: h.characteristic_polynomial() # long time + sage: h.characteristic_polynomial.clear_cache() # long time # optional - sage.combinat + sage: h.characteristic_polynomial() # long time # optional - sage.combinat x^4 - 12*x^3 + 48*x^2 - 64*x - sage: h = hyperplane_arrangements.Shi("A3",m=2) - sage: h.characteristic_polynomial() + sage: h = hyperplane_arrangements.Shi("A3", m=2) # optional - sage.combinat + sage: h.characteristic_polynomial() # optional - sage.combinat x^4 - 24*x^3 + 192*x^2 - 512*x - sage: h.characteristic_polynomial.clear_cache() - sage: h.characteristic_polynomial() + sage: h.characteristic_polynomial.clear_cache() # optional - sage.combinat + sage: h.characteristic_polynomial() # optional - sage.combinat x^4 - 24*x^3 + 192*x^2 - 512*x - sage: h = hyperplane_arrangements.Shi("B3",m=3) - sage: h.characteristic_polynomial() + sage: h = hyperplane_arrangements.Shi("B3", m=3) # optional - sage.combinat + sage: h.characteristic_polynomial() # optional - sage.combinat x^3 - 54*x^2 + 972*x - 5832 - sage: h.characteristic_polynomial.clear_cache() - sage: h.characteristic_polynomial() + sage: h.characteristic_polynomial.clear_cache() # optional - sage.combinat + sage: h.characteristic_polynomial() # optional - sage.combinat 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 05176797415..016f2c9b409 100644 --- a/src/sage/geometry/hyperplane_arrangement/plot.py +++ b/src/sage/geometry/hyperplane_arrangement/plot.py @@ -56,25 +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, hyperplane_legend=False) # optional - sage.plot + sage: A.plot(hyperplane_opacities=0.5, hyperplane_labels=True, # optional - 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) # optional - 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]]) # optional - 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]]]) # optional - 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) # optional - sage.plot Graphics object consisting of 3 graphics primitives - sage: h.plot(ranges=[-1, 10]) # optional - sage.plot + sage: h.plot(ranges=[-1, 10]) # optional - 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]]) # optional - sage.plot Graphics object consisting of 3 graphics primitives sage: a = hyperplane_arrangements.coordinate(3) @@ -83,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) # optional - sage.plot Graphics3d Object sage: opts['hyperplane_labels'] = 'short' - sage: a.plot(**opts) # optional - sage.plot + sage: a.plot(**opts) # optional - 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']) # optional - 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') # optional - 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) # optional - 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']) # optional - sage.plot Graphics3d Object """ from copy import copy @@ -144,8 +145,8 @@ def plot(hyperplane_arrangement, **kwds): EXAMPLES:: - sage: B = hyperplane_arrangements.semiorder(4) - sage: B.plot() # optional - sage.plot + sage: B = hyperplane_arrangements.semiorder(4) # optional - sage.combinat + sage: B.plot() # optional - sage.combinat sage.plot Displaying the essentialization. Graphics3d Object """ @@ -330,33 +331,34 @@ 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 # optional - 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') # optional - 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() # optional - 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)) # optional - 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: opts = {'hyperplane_label': True, 'label_color': 'green', + ....: 'label_fontsize': 24, 'label_offset': (0,1.5)} + sage: b.plot(**opts) # optional - sage.plot Graphics object consisting of 2 graphics primitives sage: H3. = HyperplaneArrangements(QQ) sage: c = 2*x + 3*y + 4*z + 5 - sage: c.plot() # optional - sage.plot + sage: c.plot() # optional - sage.plot Graphics3d Object - sage: c.plot(label_offset=(1,0,1), color='green', label_color='red', frame=False) # optional - sage.plot + sage: c.plot(label_offset=(1,0,1), color='green', label_color='red', # optional - sage.plot + ....: 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) # optional - sage.plot 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) # optional - sage.plot Graphics3d Object """ if hyperplane.base_ring().characteristic(): @@ -484,22 +486,22 @@ def legend_3d(hyperplane_arrangement, hyperplane_colors, length): EXAMPLES:: - sage: a = hyperplane_arrangements.semiorder(3) + sage: a = hyperplane_arrangements.semiorder(3) # optional - sage.combinat sage: from sage.geometry.hyperplane_arrangement.plot import legend_3d - sage: legend_3d(a, list(colors.values())[:6],length='long') + sage: legend_3d(a, list(colors.values())[:6], length='long') # optional - sage.combinat sage.plot Graphics object consisting of 6 graphics primitives - sage: b = hyperplane_arrangements.semiorder(4) - sage: c = b.essentialization() - sage: legend_3d(c, list(colors.values())[:12], length='long') + 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 Graphics object consisting of 12 graphics primitives - sage: legend_3d(c, list(colors.values())[:12], length='short') + sage: legend_3d(c, list(colors.values())[:12], length='short') # optional - sage.plot Graphics object consisting of 12 graphics primitives - sage: p = legend_3d(c, list(colors.values())[:12], length='short') - sage: p.set_legend_options(ncol=4) - sage: type(p) + sage: p = legend_3d(c, list(colors.values())[:12], length='short') # optional - sage.plot + sage: p.set_legend_options(ncol=4) # optional - sage.plot + sage: type(p) # optional - sage.plot """ if hyperplane_arrangement.dimension() != 3: diff --git a/src/sage/geometry/integral_points.pxi b/src/sage/geometry/integral_points.pxi index e5ddce891a1..dae34bc99af 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) - sage: len( rectangular_box_points([-100], [100], polytope) ) + sage: polytope = Polyhedron([[1], [10*pi.n()]], base_ring=RDF) # optional - sage.symbolic + sage: len(rectangular_box_points([-100], [100], polytope)) # optional - sage.symbolic 31 sage: halfplane = Polyhedron(ieqs=[(-1,1,0)]) @@ -488,15 +488,15 @@ cpdef rectangular_box_points(list box_min, list box_max, Using a PPL polyhedron:: - 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) + 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 ((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 +739,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) + sage: Inequality_generic([2 * pi, sqrt(3), 7/2], -5.5) # optional - sage.symbolic generic: (2*pi, sqrt(3), 7/2) x + -5.50000000000000 >= 0 """ @@ -761,7 +761,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) + sage: Inequality_generic([2 * pi, sqrt(3), 7/2], -5.5) # optional - sage.symbolic generic: (2*pi, sqrt(3), 7/2) x + -5.50000000000000 >= 0 """ self.A = A @@ -1131,16 +1131,16 @@ cdef class InequalityCollection: EXAMPLES:: - 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 ) + 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 The collection of inequalities integer: (0, 1, 0) x + -1 >= 0 integer: (0, -1, 0) x + 1 >= 0 @@ -1191,8 +1191,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) # optional - sage.rings.number_field + sage: P.integral_points() # optional - 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 778e7934d3f..9ec62336eeb 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -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() + sage: p.faces() # optional - sage.graphs ((-1-d lattice polytope in 3-d lattice M,),) """ if isinstance(data, LatticePolytopeClass): @@ -765,15 +765,15 @@ def _compute_facets(self): sage: p = LatticePolytope([], lattice=ToricLattice(3).dual()); p -1-d lattice polytope in 3-d lattice M - sage: a = p.faces()[0][0] + sage: a = p.faces()[0][0] # optional - 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]; a + sage: a = p.faces()[0][0]; a # optional - sage.graphs -1-d lattice polytope in 3-d lattice M - sage: a.facet_normals() + sage: a.facet_normals() # optional - sage.graphs Empty collection in 3-d lattice N - sage: a + sage: a # optional - sage.graphs -1-d lattice polytope in 3-d lattice M """ assert not hasattr(self, "_facet_normals") @@ -1335,7 +1335,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)): + sage: for i, face in enumerate(o.faces(0)): # optional - sage.graphs ....: if face.vertex(0) != o.vertex(i): ....: print("Wrong order!") """ @@ -1380,10 +1380,10 @@ def adjacent(self): EXAMPLES:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.adjacent() + sage: o.adjacent() # optional - sage.graphs () - sage: face = o.faces(1)[0] - sage: face.adjacent() + sage: face = o.faces(1)[0] # optional - sage.graphs + sage: face.adjacent() # optional - 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 +1505,12 @@ def ambient(self): 3-d reflexive polytope in 3-d lattice M sage: o.ambient() is o True - sage: face = o.faces(1)[0] - sage: face + sage: face = o.faces(1)[0] # optional - sage.graphs + sage: face # optional - sage.graphs 1-d face of 3-d reflexive polytope in 3-d lattice M - sage: face.ambient() + sage: face.ambient() # optional - sage.graphs 3-d reflexive polytope in 3-d lattice M - sage: face.ambient() is o + sage: face.ambient() is o # optional - sage.graphs True """ return self._ambient @@ -1533,14 +1533,14 @@ def ambient_facet_indices(self): But each of its other faces is contained in one or more facets:: - sage: face = o.faces(1)[0] - sage: face.ambient_facet_indices() + sage: face = o.faces(1)[0] # optional - sage.graphs + sage: face.ambient_facet_indices() # optional - sage.graphs (4, 5) - sage: face.vertices() + sage: face.vertices() # optional - sage.graphs M(1, 0, 0), M(0, 1, 0) in 3-d lattice M - sage: o.facets()[face.ambient_facet_indices()[0]].vertices() + sage: o.facets()[face.ambient_facet_indices()[0]].vertices() # optional - sage.graphs M(1, 0, 0), M(0, 1, 0), M(0, 0, -1) @@ -1561,10 +1561,10 @@ def ambient_point_indices(self): EXAMPLES:: sage: cube = lattice_polytope.cross_polytope(3).polar() - sage: face = cube.facets()[0] - sage: face.ambient_point_indices() # optional - palp + sage: face = cube.facets()[0] # optional - sage.graphs + sage: face.ambient_point_indices() # optional - palp sage.graphs (4, 5, 6, 7, 8, 9, 10, 11, 12) - sage: cube.points(face.ambient_point_indices()) == face.points() # optional - palp + sage: cube.points(face.ambient_point_indices()) == face.points() # optional - palp sage.graphs True """ if self._ambient is self: @@ -1587,10 +1587,10 @@ def ambient_ordered_point_indices(self): EXAMPLES:: sage: cube = lattice_polytope.cross_polytope(3).polar() - sage: face = cube.facets()[0] - sage: face.ambient_ordered_point_indices() # optional - palp + sage: face = cube.facets()[0] # optional - sage.graphs + sage: face.ambient_ordered_point_indices() # optional - palp sage.graphs (5, 8, 4, 9, 10, 11, 6, 12, 7) - sage: cube.points(face.ambient_ordered_point_indices()) # optional - palp + sage: cube.points(face.ambient_ordered_point_indices()) # optional - palp sage.graphs N(-1, -1, -1), N(-1, -1, 0), N(-1, -1, 1), @@ -1621,8 +1621,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] - sage: face.ambient_vertex_indices() + sage: face = o.faces(1)[0] # optional - sage.graphs + sage: face.ambient_vertex_indices() # optional - sage.graphs (0, 1) """ return self._ambient_vertex_indices @@ -1657,13 +1657,13 @@ def boundary_point_indices(self): For an edge the boundary is formed by the end points:: - sage: face = square.edges()[0] - sage: face.points() + sage: face = square.edges()[0] # optional - sage.graphs + sage: face.points() # optional - sage.graphs N(-1, -1), N(-1, 1), N(-1, 0) in 2-d lattice N - sage: face.boundary_point_indices() + sage: face.boundary_point_indices() # optional - sage.graphs (0, 1) """ return tuple(i @@ -1696,8 +1696,8 @@ def boundary_points(self): For an edge the boundary is formed by the end points:: - sage: face = square.edges()[0] - sage: face.boundary_points() + sage: face = square.edges()[0] # optional - sage.graphs + sage: face.boundary_points() # optional - sage.graphs N(-1, -1), N(-1, 1) in 2-d lattice N @@ -1794,7 +1794,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)]) + sage: o.distances([1,2,sqrt(2)]) # optional - sage.symbolic Traceback (most recent call last): ... TypeError: unable to convert sqrt(2) to an element of Rational Field @@ -1842,15 +1842,15 @@ def dual(self): EXAMPLES:: sage: o = lattice_polytope.cross_polytope(4) - sage: e = o.edges()[0]; e + sage: e = o.edges()[0]; e # optional - sage.graphs 1-d face of 4-d reflexive polytope in 4-d lattice M - sage: ed = e.dual(); ed + sage: ed = e.dual(); ed # optional - sage.graphs 2-d face of 4-d reflexive polytope in 4-d lattice N - sage: ed.ambient() is e.ambient().polar() + sage: ed.ambient() is e.ambient().polar() # optional - sage.graphs True - sage: e.ambient_vertex_indices() == ed.ambient_facet_indices() + sage: e.ambient_vertex_indices() == ed.ambient_facet_indices() # optional - sage.graphs True - sage: e.ambient_facet_indices() == ed.ambient_vertex_indices() + sage: e.ambient_facet_indices() == ed.ambient_vertex_indices() # optional - sage.graphs True """ for f in self._ambient.polar().faces(codim=self.dim() + 1): @@ -1893,11 +1893,11 @@ def edges(self): EXAMPLES:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.edges() + sage: o.edges() # optional - 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()) + sage: len(o.edges()) # optional - sage.graphs 12 """ return self.faces(dim=1) @@ -1920,13 +1920,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() - sage: L + sage: L = square.face_lattice(); L # optional - 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) + sage: for level in L.level_sets(): print(level) # optional - 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, @@ -1940,31 +1939,31 @@ def face_lattice(self): For a particular face you can look at its actual vertices... :: - sage: face = L.level_sets()[1][0] - sage: face.vertices() + sage: face = L.level_sets()[1][0] # optional - sage.graphs + sage: face.vertices() # optional - 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() + sage: face.ambient_vertex_indices() # optional - sage.graphs (0,) - sage: square.vertex(0) + sage: square.vertex(0) # optional - sage.graphs 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] + sage: face is square.faces(dim=0)[0] # optional - 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] - sage: D = L.hasse_diagram() - sage: sorted(D.neighbors(face)) + 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 [-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] @@ -1972,21 +1971,21 @@ 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] - sage: face + sage: face = square.faces(0)[0] # optional - sage.graphs + sage: face # optional - sage.graphs 0-d face of 2-d lattice polytope in 2-d lattice M - sage: face.vertices() + sage: face.vertices() # optional - sage.graphs M(0, 0) in 2-d lattice M - sage: face.facets() + sage: face.facets() # optional - sage.graphs (-1-d face of 2-d lattice polytope in 2-d lattice M,) - sage: face.facet_of() + sage: face.facet_of() # optional - 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) - sage: face.adjacent() + sage: face.adjacent() # optional - sage.graphs (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() + sage: face.adjacent()[0].vertices() # optional - sage.graphs M(1, 0) in 2-d lattice M @@ -1995,20 +1994,20 @@ def face_lattice(self): sage: superp = LatticePolytope([(1,2,3,4), (5,6,7,8), ....: (1,2,4,8), (1,3,9,7)]) - sage: superp.face_lattice() + sage: superp.face_lattice() # optional - sage.graphs Finite lattice containing 16 elements with distinguished linear extension - sage: superp.face_lattice().top() + sage: superp.face_lattice().top() # optional - sage.graphs 3-d lattice polytope in 4-d lattice M - sage: p = superp.facets()[0] - sage: p + sage: p = superp.facets()[0] # optional - sage.graphs + sage: p # optional - sage.graphs 2-d face of 3-d lattice polytope in 4-d lattice M - sage: p.face_lattice() + sage: p.face_lattice() # optional - sage.graphs Finite poset containing 8 elements with distinguished linear extension - sage: p.face_lattice().bottom() + sage: p.face_lattice().bottom() # optional - sage.graphs -1-d face of 3-d lattice polytope in 4-d lattice M - sage: p.face_lattice().top() + sage: p.face_lattice().top() # optional - sage.graphs 2-d face of 3-d lattice polytope in 4-d lattice M - sage: p.face_lattice().top() is p + sage: p.face_lattice().top() is p # optional - sage.graphs True """ if self._ambient is self: @@ -2098,7 +2097,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() + sage: square.faces() # optional - 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, @@ -2112,7 +2111,7 @@ def faces(self, dim=None, codim=None): Its faces of dimension one (i.e., edges):: - sage: square.faces(dim=1) + sage: square.faces(dim=1) # optional - 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, @@ -2120,16 +2119,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) + sage: square.faces(codim=1) is square.faces(dim=1) # optional - sage.graphs True Let's pick a particular face:: - sage: face = square.faces(dim=1)[0] + sage: face = square.faces(dim=1)[0] # optional - sage.graphs Now you can look at the actual vertices of this face... :: - sage: face.vertices() + sage: face.vertices() # optional - sage.graphs M(0, 0), M(0, 1) in 2-d lattice M @@ -2137,9 +2136,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() + sage: face.ambient_vertex_indices() # optional - sage.graphs (0, 3) - sage: square.vertices(face.ambient_vertex_indices()) + sage: square.vertices(face.ambient_vertex_indices()) # optional - sage.graphs M(0, 0), M(0, 1) in 2-d lattice M @@ -2365,12 +2364,12 @@ def facet_of(self): EXAMPLES:: sage: square = LatticePolytope([(0,0), (1,0), (1,1), (0,1)]) - sage: square.facet_of() + sage: square.facet_of() # optional - sage.graphs () - sage: face = square.faces(0)[0] - sage: len(face.facet_of()) + sage: face = square.faces(0)[0] # optional - sage.graphs + sage: len(face.facet_of()) # optional - sage.graphs 2 - sage: face.facet_of()[1] + sage: face.facet_of()[1] # optional - sage.graphs 1-d face of 2-d lattice polytope in 2-d lattice M """ L = self._ambient.face_lattice() @@ -2388,11 +2387,11 @@ def facets(self): EXAMPLES:: sage: o = lattice_polytope.cross_polytope(3) - sage: o.facets() + sage: o.facets() # optional - 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()) + sage: len(o.facets()) # optional - sage.graphs 8 """ return self.faces(codim=1) @@ -2420,14 +2419,14 @@ def incidence_matrix(self): [0 1 1 0] [1 1 0 0] [1 0 0 1] - sage: o.faces(1)[0].incidence_matrix() + sage: o.faces(1)[0].incidence_matrix() # optional - 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() + sage: o.facets()[3].ambient_vertex_indices() # optional - sage.graphs (3, 4, 5, 6) TESTS:: @@ -2532,7 +2531,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() # optional - palp N( 1, 1), N( 1, -1), N(-1, -1), @@ -2543,18 +2542,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() # optional - palp (6,) Its edges also have a single interior point each:: - sage: face = square.edges()[0] - sage: face.points() + sage: face = square.edges()[0] # optional - sage.graphs + sage: face.points() # optional - sage.graphs N(-1, -1), N(-1, 1), N(-1, 0) in 2-d lattice N - sage: face.interior_point_indices() + sage: face.interior_point_indices() # optional - sage.graphs (2,) """ return tuple(i @@ -2574,14 +2573,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() # optional - palp N(0, 0) in 2-d lattice N Its edges also have a single interior point each:: - sage: face = square.edges()[0] - sage: face.interior_points() + sage: face = square.edges()[0] # optional - sage.graphs + sage: face.interior_points() # optional - sage.graphs N(-1, 0) in 2-d lattice N """ @@ -2667,7 +2666,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) + sage: p.ambient_vector_space(AA) # optional - sage.rings.number_field Vector space of dimension 2 over Algebraic Real Field """ return self.lattice().vector_space(base_field=base_field) @@ -2763,7 +2762,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) # optional - palp [ Nef-partition {0, 1, 4, 5} ⊔ {2, 3, 6, 7} (direct product), Nef-partition {0, 1, 2, 4} ⊔ {3, 5, 6, 7}, @@ -3055,13 +3054,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() + sage: o._palp_modified_normal_form() # optional - sage.graphs 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) + sage: o._palp_modified_normal_form(permutation=True) # optional - sage.graphs (M( 1, 0), M( 0, 1), M( 0, -1), @@ -3108,13 +3107,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() + sage: o._palp_native_normal_form() # optional - 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) + sage: o._palp_native_normal_form(permutation=True) # optional - sage.groups (M( 1, 0), M( 0, 1), M( 0, -1), @@ -3159,8 +3158,8 @@ 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() - sage: PM_max == o._palp_PM_max() + sage: PM_max = PM.permutation_normal_form() # optional - sage.graphs + sage: PM_max == o._palp_PM_max() # optional - sage.graphs True sage: P2 = ReflexivePolytope(2, 0) sage: PM_max, permutations = P2._palp_PM_max(check=True) @@ -3565,28 +3564,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() # optional - palp sage.plot Graphics3d Object Plot without facets and points, shown without the frame:: - sage: c.plot3d(show_facets=false, show_points=false).show(frame=False) # optional - palp sage.plot + sage: c.plot3d(show_facets=false, # optional - 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')) # optional - palp sage.plot Graphics3d Object It is also possible to plot lower dimensional polytops in 3D (let's also change labels of vertices):: - sage: lattice_polytope.cross_polytope(2).plot3d(vlabels=["A", "B", "C", "D"]) # optional - palp sage.plot + sage: c2 = lattice_polytope.cross_polytope(2) + sage: c2.plot3d(vlabels=["A", "B", "C", "D"]) # optional - 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() # optional - palp sage.plot Graphics3d Object """ dim = self.dim() @@ -3971,9 +3972,9 @@ def skeleton(self): EXAMPLES:: sage: d = lattice_polytope.cross_polytope(2) - sage: g = d.skeleton(); g # optional - palp + sage: g = d.skeleton(); g # optional - palp sage.graphs Graph on 4 vertices - sage: g.edges(sort=True) # optional - palp + sage: g.edges(sort=True) # optional - palp sage.graphs [(0, 1, None), (0, 3, None), (1, 2, None), (2, 3, None)] """ skeleton = Graph() @@ -3993,34 +3994,37 @@ def skeleton_points(self, k=1): sage: o = lattice_polytope.cross_polytope(3) sage: c = o.polar() - sage: c.skeleton_points() # optional - palp + sage: c.skeleton_points() # optional - 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: c.skeleton_points(k=1) # optional - 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: c.skeleton_points(k=0) # optional - 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 - [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] + sage: c.skeleton_points(k=2) # optional - 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 - [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] + sage: c.skeleton_points(k=3) # optional - palp sage.graphs + [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 - [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] + sage: c.skeleton_points(k=100) # optional - palp sage.graphs + [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] """ if k >= self.dim(): return list(range(self.npoints())) @@ -4074,7 +4078,7 @@ def traverse_boundary(self): EXAMPLES:: sage: p = lattice_polytope.cross_polytope(2).polar() - sage: p.traverse_boundary() + sage: p.traverse_boundary() # optional - sage.graphs [3, 0, 1, 2] """ if self.dim() != 2: @@ -4740,13 +4744,13 @@ def hodge_numbers(self): nef-partitions:: 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] # long time (4s on sage.math, 2011) # optional - palp + sage: np.hodge_numbers() # long time # optional - palp 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] # long time (13s on sage.math, 2011) # optional - palp + sage: np.hodge_numbers() # long time # optional - palp (19, 19) """ try: @@ -5092,25 +5096,26 @@ def _palp(command, polytopes, reduce_dimension=False): TESTS:: 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]) # optional - palp + sage: f = open(result_name) # optional - palp + sage: f.readlines() # optional - palp ['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() # optional - palp + sage: os.remove(result_name) # optional - palp 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]) # optional - 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], reduce_dimension=True) # optional - palp - sage: f = open(result_name) # optional - palp - sage: f.readlines() # optional - palp + sage: result_name = lattice_polytope._palp("poly.x -f", [p], # optional - palp + ....: reduce_dimension=True) + sage: f = open(result_name) # optional - palp + sage: f.readlines() # optional - palp ['M:5 4 F:4\n'] - sage: f.close() # optional - palp - sage: os.remove(result_name) # optional - palp + sage: f.close() # optional - palp + sage: os.remove(result_name) # optional - palp """ if _palp_dimension is not None: dot = command.find(".") @@ -5181,9 +5186,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) # optional - 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) # optional - sage.groups (M( 1, 0), M( 0, 1), M( 0, -1), @@ -5236,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') # optional - sage.groups (1,2) - sage: _palp_convert_permutation('0123456789bac') # optional - sage.groups + sage: _palp_convert_permutation('0123456789bac') # optional - sage.groups (11,12) """ def from_palp_index(i): @@ -5670,8 +5675,8 @@ def positive_integer_relations(points): EXAMPLES: This is a 3-dimensional reflexive polytope:: sage: p = LatticePolytope([(1,0,0), (0,1,0), - ....: (-1,-1,0), (0,0,1), (-1,0,-1)]) - sage: p.points() # optional - palp + ....: (-1,-1,0), (0,0,1), (-1,0,-1)]) + sage: p.points() # optional - palp M( 1, 0, 0), M( 0, 1, 0), M(-1, -1, 0), @@ -5683,7 +5688,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() # optional - palp [ 1 0 0 1 1 0] [ 0 1 1 -1 -1 0] [ 0 0 0 0 0 1] @@ -5692,7 +5697,8 @@ def positive_integer_relations(points): numbers. This function transforms them in such a way, that all coefficients are non-negative integers:: - sage: lattice_polytope.positive_integer_relations(p.points().column_matrix()) # optional - palp + sage: points = p.points().column_matrix() + sage: lattice_polytope.positive_integer_relations(points) # optional - palp [1 0 0 1 1 0] [1 1 1 0 0 0] [0 0 0 0 0 1] diff --git a/src/sage/geometry/polyhedron/backend_cdd_rdf.py b/src/sage/geometry/polyhedron/backend_cdd_rdf.py index 7aa60657fea..ed3f6cac169 100644 --- a/src/sage/geometry/polyhedron/backend_cdd_rdf.py +++ b/src/sage/geometry/polyhedron/backend_cdd_rdf.py @@ -1,3 +1,5 @@ +# sage.doctest: optional - sage.rings.real_double + r""" The cdd backend for polyhedral computations, floating point version """ diff --git a/src/sage/geometry/polyhedron/backend_normaliz.py b/src/sage/geometry/polyhedron/backend_normaliz.py index 8499e3704d0..ce389f090a2 100644 --- a/src/sage/geometry/polyhedron/backend_normaliz.py +++ b/src/sage/geometry/polyhedron/backend_normaliz.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - pynormaliz """ The Normaliz backend for polyhedral computations @@ -89,72 +90,74 @@ class Polyhedron_normaliz(Polyhedron_base_number_field): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], rays=[(1,1)], # optional - pynormaliz - ....: lines=[], backend='normaliz') - sage: TestSuite(p).run() # optional - pynormaliz + sage: p = Polyhedron(vertices=[(0,0), (1,0), (0,1)], + ....: rays=[(1,1)], lines=[], + ....: backend='normaliz') + sage: TestSuite(p).run() Two ways to get the full space:: - sage: Polyhedron(eqns=[[0, 0, 0]], backend='normaliz') # optional - pynormaliz + sage: Polyhedron(eqns=[[0, 0, 0]], backend='normaliz') A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 lines - sage: Polyhedron(ieqs=[[0, 0, 0]], backend='normaliz') # optional - pynormaliz + sage: Polyhedron(ieqs=[[0, 0, 0]], backend='normaliz') A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 lines A lower-dimensional affine cone; we test that there are no mysterious inequalities coming in from the homogenization:: - sage: P = Polyhedron(vertices=[(1, 1)], rays=[(0, 1)], # optional - pynormaliz + sage: P = Polyhedron(vertices=[(1, 1)], rays=[(0, 1)], ....: backend='normaliz') - sage: P.n_inequalities() # optional - pynormaliz + sage: P.n_inequalities() 1 - sage: P.equations() # optional - pynormaliz + sage: P.equations() (An equation (1, 0) x - 1 == 0,) The empty polyhedron:: - sage: P=Polyhedron(ieqs=[[-2, 1, 1], [-3, -1, -1], [-4, 1, -2]], # optional - pynormaliz - ....: backend='normaliz') - sage: P # optional - pynormaliz + sage: P = Polyhedron(ieqs=[[-2, 1, 1], [-3, -1, -1], [-4, 1, -2]], + ....: backend='normaliz') + sage: P The empty polyhedron in QQ^2 - sage: P.Vrepresentation() # optional - pynormaliz + sage: P.Vrepresentation() () - sage: P.Hrepresentation() # optional - pynormaliz + sage: P.Hrepresentation() (An equation -1 == 0,) TESTS: Tests copied from various methods in :mod:`sage.geometry.polyhedron.base`:: - sage: p = Polyhedron(vertices = [[1,0,0], [0,1,0], [0,0,1]], # optional - pynormaliz + sage: p = Polyhedron(vertices=[[1,0,0], [0,1,0], [0,0,1]], ....: backend='normaliz') - sage: p.n_equations() # optional - pynormaliz + sage: p.n_equations() 1 - sage: p.n_inequalities() # optional - pynormaliz + sage: p.n_inequalities() 3 - sage: p = Polyhedron(vertices = [[t,t^2,t^3] for t in range(6)], # optional - pynormaliz + sage: p = Polyhedron(vertices=[[t,t^2,t^3] for t in range(6)], ....: backend='normaliz') - sage: p.n_facets() # optional - pynormaliz + sage: p.n_facets() 8 - sage: p = Polyhedron(vertices = [[1,0],[0,1],[1,1]], rays=[[1,1]], # optional - pynormaliz + sage: p = Polyhedron(vertices=[[1,0], [0,1], [1,1]], rays=[[1,1]], ....: backend='normaliz') - sage: p.n_vertices() # optional - pynormaliz + sage: p.n_vertices() 2 - sage: p = Polyhedron(vertices = [[1,0],[0,1]], rays=[[1,1]], # optional - pynormaliz + sage: p = Polyhedron(vertices=[[1,0], [0,1]], rays=[[1,1]], ....: backend='normaliz') - sage: p.n_rays() # optional - pynormaliz + sage: p.n_rays() 1 - sage: p = Polyhedron(vertices = [[0,0]], rays=[[0,1],[0,-1]], # optional - pynormaliz + sage: p = Polyhedron(vertices=[[0,0]], rays=[[0,1], [0,-1]], ....: backend='normaliz') - sage: p.n_lines() # optional - pynormaliz + sage: p.n_lines() 1 Algebraic polyhedra:: - sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], backend='normaliz', verbose=True) # optional - pynormaliz # optional - sage.rings.number_field + sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], # optional - sage.rings.number_field sage.symbolic + ....: backend='normaliz', verbose=True) # ----8<---- Equivalent Normaliz input file ----8<---- amb_space 1 number_field min_poly (a^2 - 2) embedding [1.414213562373095 +/- 2.99e-16] @@ -165,16 +168,23 @@ 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 - pynormaliz # optional - sage.rings.number_field - A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - pynormaliz # optional - sage.rings.number_field + sage: P # optional - 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 (A vertex at (1), A vertex at (sqrt(2))) - sage: P = polytopes.icosahedron(exact=True, backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field - sage: P # optional - pynormaliz # optional - 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(vertices=[[sqrt(2)], [AA.polynomial_root(x^3-2, RIF(0,3))]], backend='normaliz', verbose=True) # optional - pynormaliz # optional - sage.rings.number_field + sage: P = polytopes.icosahedron(exact=True, # optional - sage.rings.number_field + ....: backend='normaliz'); P + 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) + sage: P = Polyhedron(vertices=[[sqrt(2)], # optional - 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<---- amb_space 1 number_field min_poly (a^6 - 2) embedding [1.122462048309373 +/- 5.38e-16] @@ -185,9 +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 - pynormaliz # optional - sage.rings.number_field - A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - pynormaliz # optional - sage.rings.number_field + sage: P # optional - 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 (A vertex at (2^(1/3)), A vertex at (sqrt(2))) """ @@ -200,14 +211,14 @@ def __init__(self, parent, Vrep, Hrep, normaliz_cone=None, normaliz_data=None, i TESTS:: - sage: p = Polyhedron(backend='normaliz') # optional - pynormaliz - sage: TestSuite(p).run() # optional - pynormaliz - sage: p = Polyhedron(vertices=[(1, 1)], rays=[(0, 1)], # optional - pynormaliz + sage: p = Polyhedron(backend='normaliz') + sage: TestSuite(p).run() + sage: p = Polyhedron(vertices=[(1, 1)], rays=[(0, 1)], ....: backend='normaliz') - sage: TestSuite(p).run() # optional - pynormaliz - sage: p = Polyhedron(vertices=[(-1,-1), (1,0), (1,1), (0,1)], # optional - pynormaliz + sage: TestSuite(p).run() + sage: p = Polyhedron(vertices=[(-1,-1), (1,0), (1,1), (0,1)], ....: backend='normaliz') - sage: TestSuite(p).run() # optional - pynormaliz + sage: TestSuite(p).run() """ if normaliz_cone: if Hrep is not None or Vrep is not None or normaliz_data is not None: @@ -230,29 +241,30 @@ def _nmz_result(self, normaliz_cone, property): TESTS:: - sage: p = Polyhedron(vertices=[(0, 0), (1, 0), (0, 1)], rays=[(1,1)], # optional - pynormaliz + sage: p = Polyhedron(vertices=[(0, 0), (1, 0), (0, 1)], rays=[(1,1)], ....: lines=[], backend='normaliz') - sage: p._nmz_result(p._normaliz_cone, 'EquivariantXyzzyModuleSeries') # optional - pynormaliz + sage: p._nmz_result(p._normaliz_cone, 'EquivariantXyzzyModuleSeries') Traceback (most recent call last): ... 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 - pynormaliz # optional - sage.rings.number_field + 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 ....: rays=[(-1,-a)], backend='normaliz') - sage: sorted(p._nmz_result(p._normaliz_cone, 'VerticesOfPolyhedron')) # optional - pynormaliz # optional - sage.rings.number_field + sage: sorted(p._nmz_result(p._normaliz_cone, 'VerticesOfPolyhedron')) # optional - sage.rings.number_field [[-1, a^2, 1], [1, 1, 1], [a, 3, 1]] - sage: triangulation_generators = p._nmz_result(p._normaliz_cone, 'Triangulation')[1] # optional - pynormaliz # optional - sage.rings.number_field - sage: sorted(triangulation_generators) # optional - pynormaliz # optional - sage.rings.number_field + sage: triangulation_generators = p._nmz_result(p._normaliz_cone, # optional - sage.rings.number_field + ....: 'Triangulation')[1] + sage: sorted(triangulation_generators) # optional - sage.rings.number_field [[-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 - pynormaliz # optional - sage.rings.number_field + sage: p._nmz_result(p._normaliz_cone, 'AffineDim') == 2 # optional - sage.rings.number_field True - sage: p._nmz_result(p._normaliz_cone, 'EmbeddingDim') == 3 # optional - pynormaliz # optional - sage.rings.number_field + sage: p._nmz_result(p._normaliz_cone, 'EmbeddingDim') == 3 # optional - sage.rings.number_field True - sage: p._nmz_result(p._normaliz_cone, 'ExtremeRays') # optional - pynormaliz # optional - sage.rings.number_field + sage: p._nmz_result(p._normaliz_cone, 'ExtremeRays') # optional - sage.rings.number_field [[-1/3*a^2, -1, 0]] - sage: p._nmz_result(p._normaliz_cone, 'MaximalSubspace') # optional - pynormaliz # optional - sage.rings.number_field + sage: p._nmz_result(p._normaliz_cone, 'MaximalSubspace') # optional - sage.rings.number_field [] """ def rational_handler(list): @@ -272,9 +284,9 @@ def _init_from_normaliz_cone(self, normaliz_cone, internal_base_ring): TESTS:: - sage: p = Polyhedron(backend='normaliz') # optional - pynormaliz - sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz # optional - pynormaliz - sage: Polyhedron_normaliz._init_from_Hrepresentation(p, [], []) # indirect doctest # optional - pynormaliz + sage: p = Polyhedron(backend='normaliz') + sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz + sage: Polyhedron_normaliz._init_from_Hrepresentation(p, [], []) # indirect doctest """ if internal_base_ring is None: internal_base_ring = QQ @@ -297,7 +309,7 @@ def _convert_to_pynormaliz(x): TESTS:: - sage: K. = QuadraticField(2) # optional - sage.rings.number_field + sage: K. = QuadraticField(2) # optional - sage.rings.number_field sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz as Pn sage: Pn._convert_to_pynormaliz(17) 17 @@ -309,19 +321,21 @@ 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) # optional - 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) # optional - sage.rings.number_field [[7, 2], [1, 1]] sage: Pn._convert_to_pynormaliz([[1, 2], (3, 4)]) [[1, 2], [3, 4]] Check that :trac:`29836` is fixed:: - sage: P = polytopes.simplex(backend='normaliz') # optional - pynormaliz - sage: K. = QuadraticField(2) # optional - pynormaliz # optional - sage.rings.number_field - sage: P.dilation(sqrt2) # optional - pynormaliz # optional - 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 + sage: P = polytopes.simplex(backend='normaliz') + sage: K. = QuadraticField(2) # optional - sage.rings.number_field + sage: P.dilation(sqrt2) # optional - 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 """ def _QQ_pair(x): x = QQ(x) @@ -345,24 +359,25 @@ def _init_from_normaliz_data(self, data, internal_base_ring=None, verbose=False) TESTS:: - sage: p = Polyhedron(backend='normaliz', ambient_dim=2) # optional - pynormaliz - sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_QQ_normaliz # optional - pynormaliz - sage: data = {'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} # optional - pynormaliz - sage: Polyhedron_QQ_normaliz._init_from_normaliz_data(p, data) # optional - pynormaliz - sage: p.inequalities_list() # optional - pynormaliz + sage: p = Polyhedron(backend='normaliz', ambient_dim=2) + sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_QQ_normaliz + sage: data = {'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} + sage: Polyhedron_QQ_normaliz._init_from_normaliz_data(p, data) + sage: p.inequalities_list() [[0, -1, 2], [0, 2, -1]] - sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz # optional - pynormaliz - sage: from sage.rings.qqbar import AA # optional - pynormaliz # optional - sage.rings.number_field - sage: from sage.rings.number_field.number_field import QuadraticField # optional - pynormaliz # optional - sage.rings.number_field - sage: data = {'number_field': ['a^2 - 2', 'a', '[1.4 +/- 0.1]'], # optional - pynormaliz + 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: 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 # optional - pynormaliz - sage: parent = Polyhedra_normaliz(AA, 2, 'normaliz') # optional - pynormaliz # optional - sage.rings.number_field - sage: Polyhedron_normaliz(parent, None, None, normaliz_data=data, # indirect doctest, optional - pynormaliz # optional - sage.rings.number_field + 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 + ....: 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 - pynormaliz # optional - sage.rings.number_field + sage: _.inequalities_list() # optional - sage.rings.number_field [[0, -1/2, 1], [0, 2, -1]] """ if internal_base_ring is None: @@ -376,11 +391,11 @@ def _cone_from_normaliz_data(self, data, verbose=False): EXAMPLES:: - sage: p = Polyhedron(backend='normaliz', ambient_dim=2) # optional - pynormaliz - sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_QQ_normaliz # optional - pynormaliz - sage: data = {'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} # optional - pynormaliz - sage: cone = Polyhedron_QQ_normaliz._cone_from_normaliz_data(p, data) # optional - pynormaliz - sage: p._nmz_result(cone,'SupportHyperplanes') # optional - pynormaliz + sage: p = Polyhedron(backend='normaliz', ambient_dim=2) + sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_QQ_normaliz + sage: data = {'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} + sage: cone = Polyhedron_QQ_normaliz._cone_from_normaliz_data(p, data) + sage: p._nmz_result(cone,'SupportHyperplanes') [[-1, 2, 0], [0, 0, 1], [2, -1, 0]] """ if verbose: @@ -417,10 +432,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) # optional - sage.rings.number_field sage.symbolic + sage: p._is_zero(0) # optional - sage.rings.number_field sage.symbolic True - sage: p._is_zero(1/100000) # optional - sage.rings.number_field + sage: p._is_zero(1/100000) # optional - sage.rings.number_field sage.symbolic False """ return x == 0 @@ -439,10 +454,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) # optional - sage.rings.number_field sage.symbolic + sage: p._is_nonneg(1) # optional - sage.rings.number_field sage.symbolic True - sage: p._is_nonneg(-1/100000) # optional - sage.rings.number_field + sage: p._is_nonneg(-1/100000) # optional - sage.rings.number_field sage.symbolic False """ return x >= 0 @@ -461,10 +476,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) # optional - sage.rings.number_field sage.symbolic + sage: p._is_positive(1) # optional - sage.rings.number_field sage.symbolic True - sage: p._is_positive(0) # optional - sage.rings.number_field + sage: p._is_positive(0) # optional - sage.rings.number_field sage.symbolic False """ return x > 0 @@ -492,9 +507,9 @@ def _init_from_Vrepresentation(self, vertices, rays, lines, minimize=True, verbo EXAMPLES:: - sage: p = Polyhedron(backend='normaliz') # optional - pynormaliz - sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz # optional - pynormaliz - sage: Polyhedron_normaliz._init_from_Vrepresentation(p, [], [], []) # optional - pynormaliz + sage: p = Polyhedron(backend='normaliz') + sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz + sage: Polyhedron_normaliz._init_from_Vrepresentation(p, [], [], []) """ def vert_ray_line_QQ(vertices, rays, lines): @@ -565,27 +580,30 @@ def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): EXAMPLES:: - sage: p = Polyhedron(backend='normaliz') # optional - pynormaliz - sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz # optional - pynormaliz - sage: Polyhedron_normaliz._init_from_Hrepresentation(p, [], []) # optional - pynormaliz + sage: p = Polyhedron(backend='normaliz') + sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz + sage: Polyhedron_normaliz._init_from_Hrepresentation(p, [], []) TESTS:: - sage: K. = QuadraticField(2) # optional - sage.rings.number_field - sage: p = Polyhedron(ieqs=[(1, a, 0)], backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field - sage: p & p == p # optional - pynormaliz # optional - sage.rings.number_field + 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 True Check that :trac:`30248` is fixed, that maps as input works:: - sage: q = Polyhedron(backend='normaliz', base_ring=AA, # optional - pynormaliz # optional - sage.rings.number_field + sage: q = Polyhedron(backend='normaliz', base_ring=AA, # optional - sage.rings.number_field ....: rays=[(0, 0, 1), (0, 1, -1), (1, 0, -1)]) - sage: make_new_Hrep = lambda h: 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 - pynormaliz # optional - sage.rings.number_field - sage: new_equations = map(make_new_Hrep, q.equation_generator()) # optional - pynormaliz # optional - sage.rings.number_field - sage: parent = q.parent() # optional - pynormaliz # optional - sage.rings.number_field - sage: new_q = parent.element_class(parent,None,[new_inequalities,new_equations]) # optional - pynormaliz # optional - sage.rings.number_field - sage: new_q # optional - pynormaliz # optional - sage.rings.number_field + 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 + ....: [new_inequalities, new_equations]) + sage: new_q # optional - sage.rings.number_field A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays """ @@ -669,28 +687,29 @@ def _cone_from_Vrepresentation_and_Hrepresentation(self, vertices, rays, lines, EXAMPLES:: - sage: P = polytopes.hypercube(4,backend='normaliz') * Polyhedron(rays=[[0,1]]) * Polyhedron(lines=[[1,0]]) # optional - pynormaliz - sage: P # optional - pynormaliz + sage: P = (polytopes.hypercube(4, backend='normaliz') + ....: * Polyhedron(rays=[[0,1]]) + ....: * Polyhedron(lines=[[1,0]])); P A 6-dimensional polyhedron in ZZ^8 defined as the convex hull of 16 vertices, 1 ray, 1 line - sage: cone = P._cone_from_Vrepresentation_and_Hrepresentation( # optional - pynormaliz + sage: cone = P._cone_from_Vrepresentation_and_Hrepresentation( ....: P.vertices(), P.rays(), P.lines(), ....: P.inequalities(), P.equations()) - sage: import PyNormaliz # optional - pynormaliz - sage: PyNormaliz.NmzIsComputed(cone, "VerticesOfPolyhedron") # optional - pynormaliz + sage: import PyNormaliz + sage: PyNormaliz.NmzIsComputed(cone, "VerticesOfPolyhedron") True - sage: PyNormaliz.NmzIsComputed(cone, "ExtremeRays") # optional - pynormaliz + sage: PyNormaliz.NmzIsComputed(cone, "ExtremeRays") True - sage: PyNormaliz.NmzIsComputed(cone, "MaximalSubspace") # optional - pynormaliz + sage: PyNormaliz.NmzIsComputed(cone, "MaximalSubspace") True - sage: PyNormaliz.NmzIsComputed(cone, "SupportHyperplanes") # optional - pynormaliz + sage: PyNormaliz.NmzIsComputed(cone, "SupportHyperplanes") True - sage: PyNormaliz.NmzIsComputed(cone, "Equations") # optional - pynormaliz + sage: PyNormaliz.NmzIsComputed(cone, "Equations") False All values must be specified:: - sage: cone = P._cone_from_Vrepresentation_and_Hrepresentation( # optional - pynormaliz + sage: cone = P._cone_from_Vrepresentation_and_Hrepresentation( ....: P.vertices(), None, P.lines(), ....: P.inequalities(), P.equations()) Traceback (most recent call last): @@ -699,8 +718,8 @@ def _cone_from_Vrepresentation_and_Hrepresentation(self, vertices, rays, lines, This method cannot be used for the empty cone:: - sage: P = Polyhedron(backend='normaliz') # optional - pynormaliz - sage: cone = P._cone_from_Vrepresentation_and_Hrepresentation( # optional - pynormaliz + sage: P = Polyhedron(backend='normaliz') + sage: cone = P._cone_from_Vrepresentation_and_Hrepresentation( ....: P.vertices(), P.rays(), P.lines(), ....: P.inequalities(), P.equations()) Traceback (most recent call last): @@ -713,32 +732,39 @@ def _cone_from_Vrepresentation_and_Hrepresentation(self, vertices, rays, lines, ....: cone = P._cone_from_Vrepresentation_and_Hrepresentation(P.vertices(),P.rays(),P.lines(),P.inequalities(),P.equations()) ....: cone2 = P._normaliz_cone ....: args = ['Equations','VerticesOfPolyhedron','ExtremeRays','SupportHyperplanes','MaximalSubspace'] - ....: return all(P._nmz_result(cone,arg) == P._nmz_result(cone2,arg) for arg in args) - sage: test_poly(polytopes.simplex(backend='normaliz')) # optional - pynormaliz + ....: return all(P._nmz_result(cone,arg) == P._nmz_result(cone2, arg) + ....: for arg in args) + sage: test_poly(polytopes.simplex(backend='normaliz')) True - sage: test_poly(polytopes.dodecahedron(backend='normaliz')) # optional - pynormaliz # optional - sage.rings.number_field + sage: test_poly(polytopes.dodecahedron(backend='normaliz')) # optional - sage.rings.number_field True - sage: test_poly(Polyhedron(vertices=[[1,0],[0,1]],rays=[[1,1]], backend='normaliz')) # optional - pynormaliz + sage: test_poly(Polyhedron(vertices=[[1,0], [0,1]], rays=[[1,1]], + ....: backend='normaliz')) True - sage: test_poly(Polyhedron(vertices=[[-1,0],[1,0]],lines=[[0,1]], backend='normaliz')) # optional - pynormaliz + sage: test_poly(Polyhedron(vertices=[[-1,0], [1,0]], lines=[[0,1]], + ....: backend='normaliz')) True - sage: test_poly(Polyhedron(rays=[[1,0,0],[0,1,0]], backend='normaliz')) # optional - pynormaliz + sage: test_poly(Polyhedron(rays=[[1,0,0],[0,1,0]], + ....: backend='normaliz')) True - sage: test_poly(Polyhedron(vertices=[[1,0,0],[0,1,0]], rays=[[1,0,0],[0,1,0]], backend='normaliz')) # optional - pynormaliz + sage: test_poly(Polyhedron(vertices=[[1,0,0], [0,1,0]], rays=[[1,0,0], [0,1,0]], + ....: backend='normaliz')) True - sage: test_poly(Polyhedron(vertices=[[0,0,0],[0,1,1],[1,0,1],[-1,-1,1]],rays=[[0,0,1]], backend='normaliz')) # optional - pynormaliz + sage: test_poly(Polyhedron(vertices=[[0,0,0], [0,1,1], [1,0,1], [-1,-1,1]], + ....: rays=[[0,0,1]], + ....: backend='normaliz')) True Old input format will give a meaningful error message:: - sage: cone = P._cone_from_Vrepresentation_and_Hrepresentation( # optional - pynormaliz + sage: cone = P._cone_from_Vrepresentation_and_Hrepresentation( ....: P.vertices(), P.rays(), ....: P.inequalities(), P.equations()) Traceback (most recent call last): ... ValueError: the specification of this method has changed; please specify the lines as well - sage: cone = P._cone_from_Vrepresentation_and_Hrepresentation( # optional - pynormaliz + sage: cone = P._cone_from_Vrepresentation_and_Hrepresentation( ....: P.vertices(), P.rays(), ....: P.inequalities(), P.equations(), True) Traceback (most recent call last): @@ -747,11 +773,12 @@ def _cone_from_Vrepresentation_and_Hrepresentation(self, vertices, rays, lines, Check that :trac:`30891` is fixed:: - sage: p = Polyhedron(vertices=[(-3,-3), (3,0), (3,3), (0,3)], backend='normaliz') # optional - pynormaliz - sage: q = loads(p.dumps()) # optional - pynormaliz - sage: q.volume() # optional - pynormaliz + sage: p = Polyhedron(vertices=[(-3,-3), (3,0), (3,3), (0,3)], + ....: backend='normaliz') + sage: q = loads(p.dumps()) + sage: q.volume() 18 - sage: q.ehrhart_series() # optional - pynormaliz + sage: q.ehrhart_series() (13*t^2 + 22*t + 1)/(-t^3 + 3*t^2 - 3*t + 1) """ if eqns in (True, False, None): @@ -856,21 +883,21 @@ def _test_far_facet_condition(self, tester=None, **options): TESTS:: - sage: P = Polyhedron(rays=[[1,1]], backend='normaliz') # optional - pynormaliz - sage: P._test_far_facet_condition() # optional - pynormaliz + sage: P = Polyhedron(rays=[[1,1]], backend='normaliz') + sage: P._test_far_facet_condition() - sage: P = Polyhedron(vertices=[[1,0], [0,1]], # optional - pynormaliz + sage: P = Polyhedron(vertices=[[1,0], [0,1]], ....: rays=[[1,1]], backend='normaliz') - sage: P._test_far_facet_condition() # optional - pynormaliz + sage: P._test_far_facet_condition() - sage: P = Polyhedron(rays=[[1,1,0]], # optional - pynormaliz + sage: P = Polyhedron(rays=[[1,1,0]], ....: lines=[[0,0,1]], backend='normaliz') - sage: P._test_far_facet_condition() # optional - pynormaliz + sage: P._test_far_facet_condition() - sage: P = Polyhedron(vertices=[[1,0,0], [0,1,0]], # optional - pynormaliz + sage: P = Polyhedron(vertices=[[1,0,0], [0,1,0]], ....: rays=[[1,1,0]], ....: lines=[[0,0,1]], backend='normaliz') - sage: P._test_far_facet_condition() # optional - pynormaliz + sage: P._test_far_facet_condition() """ if tester is None: tester = self._tester(**options) @@ -897,13 +924,13 @@ def _init_Vrepresentation_from_normaliz(self): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,1/2),(2,0),(4,5/6)], # indirect doctest # optional - pynormaliz + sage: p = Polyhedron(vertices=[(0,1/2), (2,0), (4,5/6)], # indirect doctest ....: backend='normaliz') - sage: p.Hrepresentation() # optional - pynormaliz + sage: p.Hrepresentation() (An inequality (-5, 12) x + 10 >= 0, An inequality (1, -12) x + 6 >= 0, An inequality (1, 4) x - 2 >= 0) - sage: p.Vrepresentation() # optional - pynormaliz + sage: p.Vrepresentation() (A vertex at (0, 1/2), A vertex at (2, 0), A vertex at (4, 5/6)) """ self._Vrepresentation = [] @@ -928,13 +955,13 @@ def _init_Hrepresentation_from_normaliz(self): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,1/2), (2,0), (4,5/6)], # indirect doctest # optional - pynormaliz + sage: p = Polyhedron(vertices=[(0,1/2), (2,0), (4,5/6)], # indirect doctest ....: backend='normaliz') - sage: p.Hrepresentation() # optional - pynormaliz + sage: p.Hrepresentation() (An inequality (-5, 12) x + 10 >= 0, An inequality (1, -12) x + 6 >= 0, An inequality (1, 4) x - 2 >= 0) - sage: p.Vrepresentation() # optional - pynormaliz + sage: p.Vrepresentation() (A vertex at (0, 1/2), A vertex at (2, 0), A vertex at (4, 5/6)) """ self._Hrepresentation = [] @@ -956,15 +983,15 @@ def _init_empty_polyhedron(self): TESTS:: - sage: empty = Polyhedron(backend='normaliz'); empty # optional - pynormaliz + sage: empty = Polyhedron(backend='normaliz'); empty The empty polyhedron in ZZ^0 - sage: empty.Vrepresentation() # optional - pynormaliz + sage: empty.Vrepresentation() () - sage: empty.Hrepresentation() # optional - pynormaliz + sage: empty.Hrepresentation() (An equation -1 == 0,) - sage: Polyhedron(vertices = [], backend='normaliz') # optional - pynormaliz + sage: Polyhedron(vertices=[], backend='normaliz') The empty polyhedron in ZZ^0 - sage: Polyhedron(backend='normaliz')._init_empty_polyhedron() # optional - pynormaliz + sage: Polyhedron(backend='normaliz')._init_empty_polyhedron() """ super()._init_empty_polyhedron() # Can't seem to set up an empty _normaliz_cone. @@ -979,9 +1006,9 @@ def _from_normaliz_cone(cls, parent, normaliz_cone, internal_base_ring=None): TESTS:: - sage: P=Polyhedron(ieqs=[[1, 0, 2], [3, 0, -2], [3, 2, -2]], # optional - pynormaliz + sage: P=Polyhedron(ieqs=[[1, 0, 2], [3, 0, -2], [3, 2, -2]], ....: backend='normaliz') - sage: PI = P.integral_hull() # indirect doctest; optional - pynormaliz + sage: PI = P.integral_hull() # indirect doctest """ return cls(parent, None, None, normaliz_cone=normaliz_cone, internal_base_ring=internal_base_ring) @@ -995,7 +1022,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)) # optional - sage.rings.number_field ['a^2 - 5', 'a', '[2.236067977499789 +/- 8.06e-16]'] """ R = internal_base_ring @@ -1022,11 +1049,11 @@ def _make_normaliz_cone(data, verbose=False): TESTS:: - sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz # optional - pynormaliz - sage: data = {'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} # optional - pynormaliz - sage: nmz_cone = Polyhedron_normaliz._make_normaliz_cone(data,verbose=False) # optional - pynormaliz - sage: from PyNormaliz import NmzResult # optional - pynormaliz - sage: NmzResult(nmz_cone, "ExtremeRays") # optional - pynormaliz + sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz + sage: data = {'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} + sage: nmz_cone = Polyhedron_normaliz._make_normaliz_cone(data,verbose=False) + sage: from PyNormaliz import NmzResult + sage: NmzResult(nmz_cone, "ExtremeRays") [[1, 2, 0], [2, 1, 0]] """ if verbose: @@ -1047,14 +1074,14 @@ def _get_nmzcone_data(self): The empty polyhedron:: - sage: P = Polyhedron(backend='normaliz') # optional - pynormaliz - sage: P._get_nmzcone_data() # optional - pynormaliz + sage: P = Polyhedron(backend='normaliz') + sage: P._get_nmzcone_data() {} Another simple example:: - sage: C = Polyhedron(backend='normaliz', rays=[[1, 2], [2, 1]]) # optional - pynormaliz - sage: C._get_nmzcone_data() # optional - pynormaliz + sage: C = Polyhedron(backend='normaliz', rays=[[1, 2], [2, 1]]) + sage: C._get_nmzcone_data() {'cone': [[1, 2], [2, 1]], 'inhom_equations': [], 'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]], @@ -1093,7 +1120,7 @@ def _normaliz_format(self, data, file_output=None): EXAMPLES:: - sage: P = Polyhedron(vertices=[[0, 0], [0, 1], [1, 0]], # indirect doctest; optional - pynormaliz + sage: P = Polyhedron(vertices=[[0, 0], [0, 1], [1, 0]], # indirect doctest ....: backend='normaliz', verbose=True) # ----8<---- Equivalent Normaliz input file ----8<---- amb_space 2 @@ -1148,9 +1175,9 @@ def __copy__(self): TESTS:: - sage: P = polytopes.cube(backend='normaliz') # optional - pynormaliz - sage: Q = copy(P) # optional - pynormaliz - sage: P._normaliz_cone is Q._normaliz_cone # optional - pynormaliz + sage: P = polytopes.cube(backend='normaliz') + sage: Q = copy(P) + sage: P._normaliz_cone is Q._normaliz_cone False """ other = super().__copy__() @@ -1167,8 +1194,8 @@ def __getstate__(self): TESTS:: - sage: P = polytopes.simplex(backend='normaliz') # optional - pynormaliz - sage: P.__getstate__() # optional - pynormaliz + sage: P = polytopes.simplex(backend='normaliz') + sage: P.__getstate__() (Polyhedra in ZZ^4, {'_Hrepresentation': (An inequality (0, 0, 0, 1) x + 0 >= 0, An inequality (0, 0, 1, 0) x + 0 >= 0, @@ -1209,52 +1236,53 @@ def __setstate__(self, state): TESTS:: - sage: P = polytopes.permutahedron(4, backend='normaliz') # optional - pynormaliz - sage: P.volume(measure='induced_lattice', engine='normaliz') # optional - pynormaliz + sage: P = polytopes.permutahedron(4, backend='normaliz') + sage: P.volume(measure='induced_lattice', engine='normaliz') 96 - sage: P.volume.clear_cache() # optional - pynormaliz - sage: P1 = loads(dumps(P)) # indirect doctest # optional - pynormaliz - sage: P1.volume(measure='induced_lattice', engine='normaliz') # optional - pynormaliz + sage: P.volume.clear_cache() + sage: P1 = loads(dumps(P)) # indirect doctest + sage: P1.volume(measure='induced_lattice', engine='normaliz') 96 Test that the obtained cone is valid:: - sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz # optional - pynormaliz - sage: P = polytopes.permutahedron(4, backend='normaliz') # optional - pynormaliz - sage: P1 = loads(dumps(P)) # optional - pynormaliz - sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone) # optional - pynormaliz - sage: P2 == P # optional - pynormaliz + sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz + sage: P = polytopes.permutahedron(4, backend='normaliz') + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone) + sage: P2 == P True - sage: P = Polyhedron(lines=[[1,0], [0,1]], backend='normaliz') # optional - pynormaliz - sage: P1 = loads(dumps(P)) # optional - pynormaliz - sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone) # optional - pynormaliz - sage: P2 == P # optional - pynormaliz + sage: P = Polyhedron(lines=[[1,0], [0,1]], backend='normaliz') + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone) + sage: P2 == P True - sage: P = Polyhedron(backend='normaliz') # optional - pynormaliz - sage: P1 = loads(dumps(P)) # optional - pynormaliz - sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone) # optional - pynormaliz - sage: P2 == P # optional - pynormaliz + sage: P = Polyhedron(backend='normaliz') + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone) + sage: P2 == P True - sage: P = polytopes.permutahedron(4, backend='normaliz') * Polyhedron(lines=[[1]], backend='normaliz') # optional - pynormaliz - sage: P1 = loads(dumps(P)) # optional - pynormaliz - sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone) # optional - pynormaliz - sage: P2 == P # optional - pynormaliz + sage: P = polytopes.permutahedron(4, backend='normaliz') * Polyhedron(lines=[[1]], backend='normaliz') + sage: P1 = loads(dumps(P)) + sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone) + sage: P2 == P True - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field - sage: P1 = loads(dumps(P)) # optional - pynormaliz # optional - sage.rings.number_field - sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone, internal_base_ring=P1._internal_base_ring) # optional - pynormaliz # optional - sage.rings.number_field - sage: P == P2 # optional - pynormaliz # optional - sage.rings.number_field + 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 + ....: internal_base_ring=P1._internal_base_ring) + sage: P == P2 # optional - sage.rings.number_field True Test that :trac:`31820` is fixed:: - sage: P = polytopes.cube(backend='normaliz') # optional - pynormaliz - sage: v = P.Vrepresentation()[0] # optional - pynormaliz - sage: v1 = loads(v.dumps()) # optional - pynormaliz + sage: P = polytopes.cube(backend='normaliz') + sage: v = P.Vrepresentation()[0] + sage: v1 = loads(v.dumps()) """ if "_pickle_vertices" in state[1]: vertices = state[1].pop("_pickle_vertices") @@ -1294,29 +1322,31 @@ def integral_hull(self): Unbounded example from Normaliz manual, "a dull polyhedron":: - sage: P = Polyhedron(ieqs=[[1, 0, 2], [3, 0, -2], [3, 2, -2]], # optional - pynormaliz - ....: backend='normaliz') - sage: PI = P.integral_hull() # optional - pynormaliz - sage: P.plot(color='yellow') + PI.plot(color='green') # optional - pynormaliz # optional - sage.plot + 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 Graphics object consisting of 10 graphics primitives - sage: PI.Vrepresentation() # optional - pynormaliz - (A vertex at (-1, 0), A vertex at (0, 1), A ray in the direction (1, 0)) + sage: PI.Vrepresentation() + (A vertex at (-1, 0), + A vertex at (0, 1), + A ray in the direction (1, 0)) Nonpointed case:: - sage: P = Polyhedron(vertices=[[1/2, 1/3]], rays=[[1, 1]], # optional - pynormaliz - ....: lines=[[-1, 1]], backend='normaliz') - sage: PI = P.integral_hull() # optional - pynormaliz - sage: PI.Vrepresentation() # optional - pynormaliz + sage: P = Polyhedron(vertices=[[1/2, 1/3]], rays=[[1, 1]], + ....: lines=[[-1, 1]], backend='normaliz') + sage: PI = P.integral_hull() + sage: PI.Vrepresentation() (A vertex at (1, 0), A ray in the direction (1, 0), A line in the direction (1, -1)) Empty polyhedron:: - sage: P = Polyhedron(backend='normaliz') # optional - pynormaliz - sage: PI = P.integral_hull() # optional - pynormaliz - sage: PI.Vrepresentation() # optional - pynormaliz + sage: P = Polyhedron(backend='normaliz') + sage: PI = P.integral_hull() + sage: PI.Vrepresentation() () """ if self.is_empty(): @@ -1341,14 +1371,14 @@ def _h_star_vector_normaliz(self): The `h^*`-vector of a unimodular simplex is 1:: - sage: s3 = polytopes.simplex(3,backend='normaliz') # optional - pynormaliz - sage: s3._h_star_vector_normaliz() # optional - pynormaliz + sage: s3 = polytopes.simplex(3, backend='normaliz') + sage: s3._h_star_vector_normaliz() [1] The `h^*`-vector of the `0/1`-cube is [1,4,1]:: - sage: cube = polytopes.cube(intervals='zero_one', backend='normaliz') # optional - pynormaliz - sage: cube.h_star_vector() # optional - pynormaliz + sage: cube = polytopes.cube(intervals='zero_one', backend='normaliz') + sage: cube.h_star_vector() [1, 4, 1] TESTS: @@ -1356,9 +1386,9 @@ def _h_star_vector_normaliz(self): Check that :trac:`33847` is fixed:: sage: L = [[1, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0], [1, 0, 1, 0, 0, 0], - ....: [1, 0, 0, 1, 0, 0], [1, 0, 0, 0, 1, 0], [1, 0, 0, 1, 2, 3]] - sage: P = Polyhedron(vertices=L,backend='normaliz') # optional - pynormaliz - sage: P.h_star_vector() # optional - pynormaliz + ....: [1, 0, 0, 1, 0, 0], [1, 0, 0, 0, 1, 0], [1, 0, 0, 1, 2, 3]] + sage: P = Polyhedron(vertices=L, backend='normaliz') + sage: P.h_star_vector() [1, 0, 2] """ return self.ehrhart_series().numerator().list() @@ -1395,57 +1425,57 @@ def _volume_normaliz(self, measure='euclidean'): For normaliz, the default is the euclidean volume in the ambient space and the result is a float:: - sage: s = polytopes.simplex(3,backend='normaliz') # optional - pynormaliz - sage: s._volume_normaliz() # optional - pynormaliz + sage: s = polytopes.simplex(3, backend='normaliz') + sage: s._volume_normaliz() 0.3333333333333333 One other possibility is to compute the scaled volume where a unimodular simplex has volume 1:: - sage: s._volume_normaliz(measure='induced_lattice') # optional - pynormaliz + sage: s._volume_normaliz(measure='induced_lattice') 1 sage: v = [[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: cube = Polyhedron(vertices=v,backend='normaliz') # optional - pynormaliz - sage: cube._volume_normaliz() # optional - pynormaliz + sage: cube = Polyhedron(vertices=v, backend='normaliz') + sage: cube._volume_normaliz() 1.0 - sage: cube._volume_normaliz(measure='induced_lattice') # optional - pynormaliz + sage: cube._volume_normaliz(measure='induced_lattice') 6 Or one can calculate the ambient volume, which is the above multiplied by the volume of the unimodular simplex (or zero if not full-dimensional):: - sage: cube._volume_normaliz(measure='ambient') # optional - pynormaliz + sage: cube._volume_normaliz(measure='ambient') 1 - sage: s._volume_normaliz(measure='ambient') # optional - pynormaliz + sage: s._volume_normaliz(measure='ambient') 0 TESTS: Check that :trac:`28872` is fixed:: - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field - sage: P.volume(measure='induced_lattice') # optional - pynormaliz # optional - sage.rings.number_field + sage: P = polytopes.dodecahedron(backend='normaliz') # optional - sage.rings.number_field + sage: P.volume(measure='induced_lattice') # optional - sage.rings.number_field -1056*sqrt5 + 2400 Some sanity checks that the ambient volume works correctly:: - sage: (2*cube)._volume_normaliz(measure='ambient') # optional - pynormaliz + sage: (2*cube)._volume_normaliz(measure='ambient') 8 - sage: (1/2*cube)._volume_normaliz(measure='ambient') # optional - pynormaliz + sage: (1/2*cube)._volume_normaliz(measure='ambient') 1/8 - sage: s._volume_normaliz(measure='ambient') # optional - pynormaliz + sage: s._volume_normaliz(measure='ambient') 0 - sage: P = polytopes.regular_polygon(3, backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field - sage: P._volume_normaliz('ambient') == P.volume(engine='internal') # optional - pynormaliz # optional - sage.rings.number_field + 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 True - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field - sage: P._volume_normaliz('ambient') == P.volume(engine='internal') # optional - pynormaliz # optional - sage.rings.number_field + 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 True - sage: P = Polyhedron(rays=[[1]], backend='normaliz') # optional - pynormaliz - sage: P.volume() # optional - pynormaliz + sage: P = Polyhedron(rays=[[1]], backend='normaliz') + sage: P.volume() +Infinity """ cone = self._normaliz_cone @@ -1489,26 +1519,26 @@ def _triangulate_normaliz(self): EXAMPLES:: - sage: P = Polyhedron(vertices=[[0,0,1],[1,0,1],[0,1,1],[1,1,1]],backend='normaliz') # optional - pynormaliz - sage: P._triangulate_normaliz() # optional - pynormaliz + sage: P = Polyhedron(vertices=[[0,0,1], [1,0,1], [0,1,1], [1,1,1]], backend='normaliz') + sage: P._triangulate_normaliz() [(0, 1, 2), (1, 2, 3)] - sage: C1 = Polyhedron(rays=[[0,0,1],[1,0,1],[0,1,1],[1,1,1]],backend='normaliz') # optional - pynormaliz - sage: C1._triangulate_normaliz() # optional - pynormaliz + sage: C1 = Polyhedron(rays=[[0,0,1], [1,0,1], [0,1,1], [1,1,1]], backend='normaliz') + sage: C1._triangulate_normaliz() [(0, 1, 2), (1, 2, 3)] - sage: C2 = Polyhedron(rays=[[1,0,1],[0,0,1],[0,1,1],[1,1,10/9]],backend='normaliz') # optional - pynormaliz - sage: C2._triangulate_normaliz() # optional - pynormaliz + sage: C2 = Polyhedron(rays=[[1,0,1], [0,0,1], [0,1,1], [1,1,10/9]], backend='normaliz') + sage: C2._triangulate_normaliz() [(0, 1, 2), (1, 2, 3)] Works only for cones and compact polyhedra:: - sage: P = polytopes.cube(backend='normaliz') # optional - pynormaliz - sage: Q = Polyhedron(rays=[[0,1]], backend='normaliz') # optional - pynormaliz - sage: R = Polyhedron(lines=[[0,1]], backend='normaliz') # optional - pynormaliz - sage: (P*Q)._triangulate_normaliz() # optional - pynormaliz + sage: P = polytopes.cube(backend='normaliz') + sage: Q = Polyhedron(rays=[[0,1]], backend='normaliz') + sage: R = Polyhedron(lines=[[0,1]], backend='normaliz') + sage: (P*Q)._triangulate_normaliz() Traceback (most recent call last): ... NotImplementedError: triangulation of non-compact polyhedra that are not cones is not supported - sage: (P*R)._triangulate_normaliz() # optional - pynormaliz + sage: (P*R)._triangulate_normaliz() Traceback (most recent call last): ... NotImplementedError: triangulation of non-compact not pointed polyhedron is not supported @@ -1517,8 +1547,8 @@ def _triangulate_normaliz(self): Check that :trac:`30531` is fixed:: - sage: P = polytopes.cube(backend='normaliz')*AA(2).sqrt() # optional - pynormaliz - sage: P._triangulate_normaliz() # optional - pynormaliz + sage: P = polytopes.cube(backend='normaliz')*AA(2).sqrt() + sage: P._triangulate_normaliz() [(0, 1, 2, 4), (1, 2, 4, 3), (1, 3, 4, 5), @@ -1528,8 +1558,9 @@ def _triangulate_normaliz(self): :: - sage: C1 = Polyhedron(rays=[[0,0,1],[1,0,AA(2).sqrt()],[0,1,1],[1,1,1]], backend='normaliz') # optional - pynormaliz - sage: C1._triangulate_normaliz() # optional - pynormaliz + sage: C1 = Polyhedron(rays=[[0,0,1], [1,0,AA(2).sqrt()], [0,1,1], [1,1,1]], + ....: backend='normaliz') + sage: C1._triangulate_normaliz() [(0, 1, 3), (0, 3, 2)] """ if self.lines(): @@ -1605,10 +1636,10 @@ class Polyhedron_QQ_normaliz(Polyhedron_normaliz, Polyhedron_QQ): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], # optional - pynormaliz + sage: p = Polyhedron(vertices=[(0,0), (1,0), (0,1)], ....: rays=[(1,1)], lines=[], ....: backend='normaliz', base_ring=QQ) - sage: TestSuite(p).run() # optional - pynormaliz + sage: TestSuite(p).run() """ @cached_method(do_pickle=True) @@ -1630,34 +1661,37 @@ def ehrhart_series(self, variable='t'): EXAMPLES:: - sage: S = Polyhedron(vertices=[[0,1],[1,0]], backend='normaliz') # optional - pynormaliz - sage: ES = S.ehrhart_series() # optional - pynormaliz - sage: ES.numerator() # optional - pynormaliz + sage: S = Polyhedron(vertices=[[0,1], [1,0]], backend='normaliz') + sage: ES = S.ehrhart_series() + sage: ES.numerator() 1 - sage: ES.denominator().factor() # optional - pynormaliz + sage: ES.denominator().factor() (t - 1)^2 - 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]],backend='normaliz') # optional - pynormaliz - sage: ES = C.ehrhart_series() # optional - pynormaliz - sage: ES.numerator() # optional - pynormaliz + 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]], + ....: backend='normaliz') + sage: ES = C.ehrhart_series() + sage: ES.numerator() t^2 + 4*t + 1 - sage: ES.denominator().factor() # optional - pynormaliz + sage: ES.denominator().factor() (t - 1)^4 The following example is from the Normaliz manual contained in the file ``rational.in``:: - sage: rat_poly = Polyhedron(vertices=[[1/2,1/2],[-1/3,-1/3],[1/4,-1/2]],backend='normaliz') # optional - pynormaliz - sage: ES = rat_poly.ehrhart_series() # optional - pynormaliz - sage: ES.numerator() # optional - pynormaliz + sage: rat_poly = Polyhedron(vertices=[[1/2,1/2], [-1/3,-1/3], [1/4,-1/2]], + ....: backend='normaliz') + sage: ES = rat_poly.ehrhart_series() + sage: ES.numerator() 2*t^6 + 3*t^5 + 4*t^4 + 3*t^3 + t^2 + t + 1 - sage: ES.denominator().factor() # optional - pynormaliz + sage: ES.denominator().factor() (-1) * (t + 1)^2 * (t - 1)^3 * (t^2 + 1) * (t^2 + t + 1) The polyhedron should be compact:: - sage: C = Polyhedron(backend='normaliz',rays=[[1,2],[2,1]]) # optional - pynormaliz - sage: C.ehrhart_series() # optional - pynormaliz + sage: C = Polyhedron(rays=[[1,2], [2,1]], backend='normaliz') + sage: C.ehrhart_series() Traceback (most recent call last): ... NotImplementedError: Ehrhart series can only be computed for compact polyhedron @@ -1670,8 +1704,8 @@ def ehrhart_series(self, variable='t'): Check that the Ehrhart series is pickled:: - sage: new_poly = loads(dumps(rat_poly)) # optional - pynormaliz - sage: new_poly.ehrhart_series.is_in_cache() # optional - pynormaliz + sage: new_poly = loads(dumps(rat_poly)) + sage: new_poly.ehrhart_series.is_in_cache() True """ if self.is_empty(): @@ -1720,29 +1754,31 @@ def _ehrhart_quasipolynomial_normaliz(self, variable='t'): EXAMPLES:: - 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]],backend='normaliz') # optional - pynormaliz - sage: C._ehrhart_quasipolynomial_normaliz() # optional - pynormaliz + 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]], + ....: backend='normaliz') + sage: C._ehrhart_quasipolynomial_normaliz() t^3 + 3*t^2 + 3*t + 1 - sage: P = Polyhedron(vertices=[[0,0],[3/2,0],[0,3/2],[1,1]],backend='normaliz') # optional - pynormaliz - sage: P._ehrhart_quasipolynomial_normaliz() # optional - pynormaliz + sage: P = Polyhedron(vertices=[[0,0], [3/2,0], [0,3/2], [1,1]], backend='normaliz') + sage: P._ehrhart_quasipolynomial_normaliz() (3/2*t^2 + 2*t + 1, 3/2*t^2 + 2*t + 1/2) - sage: P._ehrhart_quasipolynomial_normaliz('x') # optional - pynormaliz + sage: P._ehrhart_quasipolynomial_normaliz('x') (3/2*x^2 + 2*x + 1, 3/2*x^2 + 2*x + 1/2) The quasipolynomial evaluated at ``i`` counts the integral points in the ``i``-th dilate:: - sage: Q = Polyhedron(vertices = [[-1/3],[2/3]],backend='normaliz') # optional - pynormaliz - sage: p0,p1,p2 = Q._ehrhart_quasipolynomial_normaliz() # optional - pynormaliz - sage: r0 = [p0(i) for i in range(15)] # optional - pynormaliz - sage: r1 = [p1(i) for i in range(15)] # optional - pynormaliz - sage: r2 = [p2(i) for i in range(15)] # optional - pynormaliz - sage: result = [None]*15 # optional - pynormaliz - sage: result[::3] = r0[::3] # optional - pynormaliz - sage: result[1::3] = r1[1::3] # optional - pynormaliz - sage: result[2::3] = r2[2::3] # optional - pynormaliz - sage: result == [(i*Q).integral_points_count() for i in range(15)] # optional - pynormaliz + sage: Q = Polyhedron(vertices=[[-1/3], [2/3]], backend='normaliz') + sage: p0,p1,p2 = Q._ehrhart_quasipolynomial_normaliz() + sage: r0 = [p0(i) for i in range(15)] + sage: r1 = [p1(i) for i in range(15)] + sage: r2 = [p2(i) for i in range(15)] + sage: result = [None]*15 + sage: result[::3] = r0[::3] + sage: result[1::3] = r1[1::3] + sage: result[2::3] = r2[2::3] + sage: result == [(i*Q).integral_points_count() for i in range(15)] True @@ -1791,32 +1827,33 @@ def hilbert_series(self, grading, variable='t'): EXAMPLES:: - sage: C = Polyhedron(backend='normaliz',rays=[[0,0,1],[0,1,1],[1,0,1],[1,1,1]]) # optional - pynormaliz - sage: HS = C.hilbert_series([1,1,1]) # optional - pynormaliz - sage: HS.numerator() # optional - pynormaliz + sage: C = Polyhedron(backend='normaliz', + ....: rays=[[0,0,1], [0,1,1], [1,0,1], [1,1,1]]) + sage: HS = C.hilbert_series([1,1,1]) + sage: HS.numerator() t^2 + 1 - sage: HS.denominator().factor() # optional - pynormaliz + sage: HS.denominator().factor() (-1) * (t + 1) * (t - 1)^3 * (t^2 + t + 1) By changing the grading, you can get the Ehrhart series of the square lifted at height 1:: - sage: C.hilbert_series([0,0,1]) # optional - pynormaliz + sage: C.hilbert_series([0,0,1]) (t + 1)/(-t^3 + 3*t^2 - 3*t + 1) Here is an example ``2cone.in`` from the Normaliz manual:: - sage: C = Polyhedron(backend='normaliz',rays=[[1,3],[2,1]]) # optional - pynormaliz - sage: HS = C.hilbert_series([1,1]) # optional - pynormaliz - sage: HS.numerator() # optional - pynormaliz + sage: C = Polyhedron(backend='normaliz', rays=[[1,3], [2,1]]) + sage: HS = C.hilbert_series([1,1]) + sage: HS.numerator() t^5 + t^4 + t^3 + t^2 + 1 - sage: HS.denominator().factor() # optional - pynormaliz + sage: HS.denominator().factor() (t + 1) * (t - 1)^2 * (t^2 + 1) * (t^2 + t + 1) - sage: HS = C.hilbert_series([1,2]) # optional - pynormaliz - sage: HS.numerator() # optional - pynormaliz + sage: HS = C.hilbert_series([1,2]) + sage: HS.numerator() t^8 + t^6 + t^5 + t^3 + 1 - sage: HS.denominator().factor() # optional - pynormaliz + sage: HS.denominator().factor() (t + 1) * (t - 1)^2 * (t^2 + 1) * (t^6 + t^5 + t^4 + t^3 + t^2 + t + 1) Here is the magic square example form the Normaliz manual:: @@ -1828,9 +1865,10 @@ def hilbert_series(self, grading, variable='t'): ....: [0,1,1,0, 0, 0,-1, 0, 0,-1], ....: [0,0,1,1, 0,-1, 0, 0, 0,-1], ....: [0,1,1,0, 0,-1, 0,-1, 0, 0]] - sage: magic_square = Polyhedron(eqns=eq,backend='normaliz') & Polyhedron(rays=identity_matrix(9).rows()) # optional - pynormaliz + sage: magic_square = (Polyhedron(eqns=eq, backend='normaliz') + ....: & Polyhedron(rays=identity_matrix(9).rows())) sage: grading = [1,1,1,0,0,0,0,0,0] - sage: magic_square.hilbert_series(grading) # optional - pynormaliz + sage: magic_square.hilbert_series(grading) (t^6 + 2*t^3 + 1)/(-t^9 + 3*t^6 - 3*t^3 + 1) .. SEEALSO:: @@ -1841,8 +1879,8 @@ def hilbert_series(self, grading, variable='t'): Check that the Hilbert series is pickled:: - sage: new_magic = loads(dumps(magic_square)) # optional - pynormaliz - sage: new_magic.hilbert_series.is_in_cache(grading) # optional - pynormaliz + sage: new_magic = loads(dumps(magic_square)) + sage: new_magic.hilbert_series.is_in_cache(grading) True """ if self.is_empty(): @@ -1885,29 +1923,29 @@ def integral_points(self, threshold=10000): EXAMPLES:: - sage: Polyhedron(vertices=[(-1,-1), (1,0), (1,1), (0,1)], # optional - pynormaliz + sage: Polyhedron(vertices=[(-1,-1), (1,0), (1,1), (0,1)], ....: backend='normaliz').integral_points() ((-1, -1), (0, 0), (0, 1), (1, 0), (1, 1)) - sage: simplex = Polyhedron([(1,2,3), (2,3,7), (-2,-3,-11)], # optional - pynormaliz + sage: simplex = Polyhedron([(1,2,3), (2,3,7), (-2,-3,-11)], ....: backend='normaliz') - sage: simplex.integral_points() # optional - pynormaliz + sage: simplex.integral_points() ((-2, -3, -11), (0, 0, -2), (1, 2, 3), (2, 3, 7)) The polyhedron need not be full-dimensional:: - sage: simplex = Polyhedron([(1,2,3,5), (2,3,7,5), (-2,-3,-11,5)], # optional - pynormaliz + sage: simplex = Polyhedron([(1,2,3,5), (2,3,7,5), (-2,-3,-11,5)], ....: backend='normaliz') - sage: simplex.integral_points() # optional - pynormaliz + sage: simplex.integral_points() ((-2, -3, -11, 5), (0, 0, -2, 5), (1, 2, 3, 5), (2, 3, 7, 5)) - sage: point = Polyhedron([(2,3,7)], # optional - pynormaliz + sage: point = Polyhedron([(2,3,7)], ....: backend='normaliz') - sage: point.integral_points() # optional - pynormaliz + sage: point.integral_points() ((2, 3, 7),) - sage: empty = Polyhedron(backend='normaliz') # optional - pynormaliz - sage: empty.integral_points() # optional - pynormaliz + sage: empty = Polyhedron(backend='normaliz') + sage: empty.integral_points() () Here is a simplex where the naive algorithm of running over @@ -1915,9 +1953,9 @@ def integral_points(self, threshold=10000): enough:: sage: v = [(1,0,7,-1), (-2,-2,4,-3), (-1,-1,-1,4), (2,9,0,-5), (-2,-1,5,1)] - sage: simplex = Polyhedron(v, backend='normaliz'); simplex # optional - pynormaliz + sage: simplex = Polyhedron(v, backend='normaliz'); simplex A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 5 vertices - sage: len(simplex.integral_points()) # optional - pynormaliz + sage: len(simplex.integral_points()) 49 A rather thin polytope for which the bounding box method would @@ -1925,27 +1963,27 @@ def integral_points(self, threshold=10000): polytope, so the other backends use the bounding box method):: sage: P = Polyhedron(vertices=((0, 0), (178933,37121))) + 1/1000*polytopes.hypercube(2) - sage: P = Polyhedron(vertices=P.vertices_list(), # optional - pynormaliz + sage: P = Polyhedron(vertices=P.vertices_list(), ....: backend='normaliz') - sage: len(P.integral_points()) # optional - pynormaliz + sage: len(P.integral_points()) 434 Finally, the 3-d reflexive polytope number 4078:: sage: v = [(1,0,0), (0,1,0), (0,0,1), (0,0,-1), (0,-2,1), ....: (-1,2,-1), (-1,2,-2), (-1,1,-2), (-1,-1,2), (-1,-3,2)] - sage: P = Polyhedron(v, backend='normaliz') # optional - pynormaliz - sage: pts1 = P.integral_points() # optional - pynormaliz - sage: all(P.contains(p) for p in pts1) # optional - pynormaliz + sage: P = Polyhedron(v, backend='normaliz') + sage: pts1 = P.integral_points() + sage: all(P.contains(p) for p in pts1) True - sage: pts2 = LatticePolytope(v).points() # optional - palp - sage: for p in pts1: p.set_immutable() # optional - pynormaliz - sage: set(pts1) == set(pts2) # optional - palp # optional - pynormaliz + sage: pts2 = LatticePolytope(v).points() # optional - palp + sage: for p in pts1: p.set_immutable() + sage: set(pts1) == set(pts2) # optional - palp True - sage: timeit('Polyhedron(v, backend='normaliz').integral_points()') # not tested - random + sage: timeit('Polyhedron(v, backend='normaliz').integral_points()') # not tested - random 625 loops, best of 3: 1.41 ms per loop - sage: timeit('LatticePolytope(v).points()') # not tested - random + sage: timeit('LatticePolytope(v).points()') # not tested - random 25 loops, best of 3: 17.2 ms per loop TESTS: @@ -1954,32 +1992,32 @@ def integral_points(self, threshold=10000): Empty polyhedron in 1 dimension:: - sage: P = Polyhedron(ambient_dim=1, backend='normaliz') # optional - pynormaliz - sage: P.integral_points() # optional - pynormaliz + sage: P = Polyhedron(ambient_dim=1, backend='normaliz') + sage: P.integral_points() () Empty polyhedron in 0 dimensions:: - sage: P = Polyhedron(ambient_dim=0, backend='normaliz') # optional - pynormaliz - sage: P.integral_points() # optional - pynormaliz + sage: P = Polyhedron(ambient_dim=0, backend='normaliz') + sage: P.integral_points() () Single point in 1 dimension:: - sage: P = Polyhedron([[3]], backend='normaliz') # optional - pynormaliz - sage: P.integral_points() # optional - pynormaliz + sage: P = Polyhedron([[3]], backend='normaliz') + sage: P.integral_points() ((3),) Single non-integral point in 1 dimension:: - sage: P = Polyhedron([[1/2]], backend='normaliz') # optional - pynormaliz - sage: P.integral_points() # optional - pynormaliz + sage: P = Polyhedron([[1/2]], backend='normaliz') + sage: P.integral_points() () Single point in 0 dimensions:: - sage: P = Polyhedron([[]], backend='normaliz') # optional - pynormaliz - sage: P.integral_points() # optional - pynormaliz + sage: P = Polyhedron([[]], backend='normaliz') + sage: P.integral_points() ((),) A polytope with no integral points (:trac:`22938`):: @@ -1988,12 +2026,12 @@ def integral_points(self, threshold=10000): ....: [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, -1], ....: [-1, -1, -1, -1], [1, 1, 0, 0], [1, 0, 1, 0], ....: [1, 0, 0, 1]] - sage: P = Polyhedron(ieqs=ieqs, backend='normaliz') # optional - pynormaliz - sage: P.bounding_box() # optional - pynormaliz + sage: P = Polyhedron(ieqs=ieqs, backend='normaliz') + sage: P.bounding_box() ((-3/4, -1/2, -1/4), (-1/2, -1/4, 0)) - sage: P.bounding_box(integral_hull=True) # optional - pynormaliz + sage: P.bounding_box(integral_hull=True) (None, None) - sage: P.integral_points() # optional - pynormaliz + sage: P.integral_points() () Check the polytopes from :trac:`22984`:: @@ -2025,8 +2063,8 @@ def integral_points(self, threshold=10000): ....: [4, 0, 0, 0, 0, 0, 1, 0, 0], ....: [2, 0, 0, 0, 0, 0, 0, 1, 0], ....: [1, 0, 0, 0, 0, 0, 0, 0, 1]] - sage: P = Polyhedron(ieqs=ieqs, backend='normaliz') # optional - pynormaliz - sage: P.integral_points() # optional - pynormaliz + sage: P = Polyhedron(ieqs=ieqs, backend='normaliz') + sage: P.integral_points() ((-2, -2, -4, -5, -4, -3, -2, -1), (-2, -2, -4, -5, -4, -3, -2, 0), (-1, -2, -3, -4, -3, -2, -2, -1), @@ -2047,8 +2085,8 @@ def integral_points(self, threshold=10000): ....: [4, 0, 0, 0, 0, 0, 1, 0, 0], ....: [2, 0, 0, 0, 0, 0, 0, 1, 0], ....: [1, 0, 0, 0, 0, 0, 0, 0, 1]] - sage: P = Polyhedron(ieqs=ieqs, backend='normaliz') # optional - pynormaliz - sage: P.integral_points() # optional - pynormaliz + sage: P = Polyhedron(ieqs=ieqs, backend='normaliz') + sage: P.integral_points() ((-3, -4, -6, -8, -6, -4, -2, -1), (-3, -4, -6, -8, -6, -4, -2, 0), (-2, -2, -4, -5, -4, -3, -2, -1), @@ -2110,20 +2148,20 @@ def integral_points_generators(self): Normaliz gives a nonnegative integer basis of the lineality space:: - sage: P = Polyhedron(backend='normaliz',lines=[[2,2]]) # optional - pynormaliz - sage: P.integral_points_generators() # optional - pynormaliz + sage: P = Polyhedron(backend='normaliz', lines=[[2,2]]) + sage: P.integral_points_generators() (((0, 0),), (), ((1, 1),)) A recession cone generated by two rays:: - sage: C = Polyhedron(backend='normaliz',rays=[[1,2],[2,1]]) # optional - pynormaliz - sage: C.integral_points_generators() # optional - pynormaliz + sage: C = Polyhedron(backend='normaliz', rays=[[1,2], [2,1]]) + sage: C.integral_points_generators() (((0, 0),), ((1, 1), (1, 2), (2, 1)), ()) Empty polyhedron:: - sage: P = Polyhedron(backend='normaliz') # optional - pynormaliz - sage: P.integral_points_generators() # optional - pynormaliz + sage: P = Polyhedron(backend='normaliz') + sage: P.integral_points_generators() ((), (), ()) """ # Trivial cases: polyhedron with 0 vertices @@ -2200,16 +2238,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: 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 - pynormaliz - sage: G.is_isomorphic(SymmetricGroup(4)) # optional - pynormaliz + sage: G = S.restricted_automorphism_group(output='permutation') # optional - sage.groups + sage: G.is_isomorphic(SymmetricGroup(4)) # optional - sage.groups True - sage: len(G) # optional - pynormaliz + sage: len(G) # optional - sage.groups 24 - sage: Hstar = S._Hstar_function_normaliz(G); Hstar # optional - pynormaliz + sage: Hstar = S._Hstar_function_normaliz(G); Hstar # optional - sage.groups chi_4 - sage: G.character_table() # optional - pynormaliz + sage: G.character_table() # optional - sage.groups [ 1 -1 1 1 -1] [ 3 -1 0 -1 1] [ 2 0 -1 2 0] @@ -2221,36 +2259,37 @@ 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],[-1,0,-1],[0,1,1], # optional - pynormaliz - ....: [0,-1,-1],[1,1,1],[-1,-1,-1]], + 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 - pynormaliz - 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, acting_group = G) # optional - pynormaliz - sage: list(Dict.keys())[0] # optional - pynormaliz + 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 (0,2)(1,3)(4,6)(5,7) - sage: list(Dict.values())[0] # optional - pynormaliz + sage: list(Dict.values())[0] # optional - sage.groups [-1 0 1 0] [ 0 1 0 0] [ 0 0 1 0] [ 0 0 0 1] - sage: len(G) # optional - pynormaliz + sage: len(G) # optional - sage.groups 2 - sage: G.character_table() # optional - pynormaliz + sage: G.character_table() # optional - sage.groups [ 1 1] [ 1 -1] Then we calculate the rational function `H^*(t)`:: - sage: Hst = P._Hstar_function_normaliz(G); Hst # optional - pynormaliz - (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: Hst = P._Hstar_function_normaliz(G); Hst # optional - 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) To see the exact as written in [Stap2011]_, we can format it as ``'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 - pynormaliz + sage: lin = P._Hstar_function_normaliz(G, output='Hstar_as_lin_comb'); lin # optional - 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 @@ -2359,15 +2398,16 @@ def _Hstar_as_rat_fct(self, initial_Hstar): The expression of `H^*` as a polynomial in `t` for a 3-dimensional simplex is computed as follows:: - sage: simplex = Polyhedron(vertices=[[0,0,0],[1,0,0],[0,1,0],[0,0,1]],backend='normaliz') # optional - pynormaliz - sage: Hstar = simplex.Hstar_function(); Hstar # optional - pynormaliz # indirect doctest + 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 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 - pynormaliz - sage: char = G.character_table();char # optional - pynormaliz + sage: G = simplex.restricted_automorphism_group(output='permutation') # optional - sage.groups + sage: char = G.character_table(); char # optional - sage.groups [ 1 -1 1 1 -1] [ 3 -1 0 -1 1] [ 2 0 -1 2 0] @@ -2379,15 +2419,16 @@ def _Hstar_as_rat_fct(self, initial_Hstar): As another example, we can look at `H^*(t)` for the `\pm 1` square:: - sage: square = Polyhedron(vertices = [[1,1],[-1,1],[-1,-1],[1,-1]], backend ='normaliz') # optional - pynormaliz - sage: Hstar = square.Hstar_function() ; Hstar # optional - pynormaliz + 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 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 - pynormaliz - sage: G.character_table() # optional - pynormaliz + sage: G = square.restricted_automorphism_group(output='permutation') # optional - sage.groups + sage: G.character_table() # optional - sage.groups [ 1 1 1 1 1] [ 1 -1 -1 1 1] [ 1 -1 1 -1 1] @@ -2434,28 +2475,30 @@ 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(output='permutation') # optional - pynormaliz - 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: 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 True - sage: [Hstar, Hlin] = [p3.Hstar_function(S3), p3.Hstar_function(S3, output = 'Hstar_as_lin_comb')] # optional - pynormaliz - sage: p3._is_effective_normaliz(Hstar,Hlin) # optional - pynormaliz + 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 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],[-1,0,-1],[0,1,1], # optional - pynormaliz - ....: [0,-1,-1],[1,1,1],[-1,-1,-1]], + 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 - pynormaliz - 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 - (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 - pynormaliz - sage: P._is_effective_normaliz(Hstar, Hstar_lin) # optional - pynormaliz + 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 + (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 False """ if not Hstar.denominator().is_unit(): @@ -2480,9 +2523,9 @@ class Polyhedron_ZZ_normaliz(Polyhedron_QQ_normaliz, Polyhedron_ZZ): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], # optional - pynormaliz + sage: p = Polyhedron(vertices=[(0,0), (1,0), (0,1)], ....: rays=[(1,1)], lines=[], ....: backend='normaliz', base_ring=ZZ) - sage: TestSuite(p).run() # optional - pynormaliz + sage: TestSuite(p).run() """ pass diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 3d4a65b3df0..ff5be490df5 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)) # optional - sage.graphs + sage: TestSuite(p).run() # optional - sage.graphs :: @@ -135,13 +135,14 @@ class Polyhedron_base(Polyhedron_base7): :: - sage: P = polytopes.permutahedron(3) * Polyhedron(rays=[[0,0,1],[0,1,1],[1,2,3]]) # optional - sage.combinat - sage: TestSuite(P).run() # optional - sage.combinat + 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 = polytopes.permutahedron(3)*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]]) # optional - sage.combinat + sage: TestSuite(P).run() # optional - sage.combinat :: @@ -317,16 +318,16 @@ def boundary_complex(self): The boundary complex of the octahedron:: sage: oc = polytopes.octahedron() - sage: sc_oc = oc.boundary_complex() - sage: fl_oc = oc.face_lattice() # optional - sage.combinat - sage: fl_sc = sc_oc.face_poset() # optional - sage.combinat - sage: [len(x) for x in fl_oc.level_sets()] # optional - sage.combinat + 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 [1, 6, 12, 8, 1] - sage: [len(x) for x in fl_sc.level_sets()] # optional - sage.combinat + sage: [len(x) for x in fl_sc.level_sets()] # optional - sage.combinat sage.graphs [6, 12, 8] - sage: sc_oc.euler_characteristic() + sage: sc_oc.euler_characteristic() # optional - sage.graphs 2 - sage: sc_oc.homology() + sage: sc_oc.homology() # optional - sage.graphs {0: 0, 1: 0, 2: Z} The polyhedron should be simplicial:: @@ -463,7 +464,7 @@ def is_inscribed(self, certificate=False): EXAMPLES:: - sage: q = Polyhedron(vertices = [[1,1,1,1],[-1,-1,1,1],[1,-1,-1,1], + sage: q = Polyhedron(vertices=[[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],[0,0,10/13,-24/13], ....: [0,0,-10/13,-24/13]]) @@ -555,7 +556,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): # optional - sage.combinat ....: P1 = parent._element_constructor_( ....: [V1, [], []], [H, []], Vrep_minimal=True, Hrep_minimal=True) ....: assert P1.is_inscribed() @@ -623,7 +624,7 @@ def hyperplane_arrangement(self): EXAMPLES:: sage: p = polytopes.hypercube(2) - sage: p.hyperplane_arrangement() # optional - sage.combinat + sage: p.hyperplane_arrangement() # optional - sage.combinat Arrangement <-t0 + 1 | -t1 + 1 | t1 + 1 | t0 + 1> """ names = tuple('t' + str(i) for i in range(self.ambient_dim())) @@ -657,7 +658,7 @@ def normal_fan(self, direction='inner'): EXAMPLES:: - sage: S = Polyhedron(vertices = [[0, 0], [1, 0], [0, 1]]) + sage: S = Polyhedron(vertices=[[0, 0], [1, 0], [0, 1]]) sage: S.normal_fan() Rational polyhedral fan in 2-d lattice N @@ -667,25 +668,27 @@ def normal_fan(self, direction='inner'): Currently, it is only possible to get the normal fan of a bounded rational polytope:: - sage: P = Polyhedron(rays = [[1, 0], [0, 1]]) + sage: P = Polyhedron(rays=[[1, 0], [0, 1]]) sage: P.normal_fan() Traceback (most recent call last): ... NotImplementedError: the normal fan is only supported for polytopes (compact polyhedra). - sage: Q = Polyhedron(vertices = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]) + sage: Q = Polyhedron(vertices=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]) sage: Q.normal_fan() Traceback (most recent call last): ... ValueError: the normal fan is only defined for full-dimensional polytopes - sage: R = Polyhedron(vertices=[[0, 0], [AA(sqrt(2)), 0], [0, AA(sqrt(2))]]) # optional - sage.rings.number_field - sage: R.normal_fan() # optional - sage.rings.number_field + sage: R = Polyhedron(vertices=[[0, 0], # optional - 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 Traceback (most recent call last): ... NotImplementedError: normal fan handles only polytopes over the rationals - sage: P = Polyhedron(vertices=[[0,0],[2,0],[0,2],[2,1],[1,2]]) + sage: P = Polyhedron(vertices=[[0,0], [2,0], [0,2], [2,1], [1,2]]) sage: P.normal_fan(direction=None) Traceback (most recent call last): ... @@ -746,13 +749,14 @@ def face_fan(self): The polytope should contain the origin in the interior:: - sage: P = Polyhedron(vertices = [[1/2, 1], [1, 1/2]]) + sage: P = Polyhedron(vertices=[[1/2, 1], [1, 1/2]]) sage: P.face_fan() Traceback (most recent call last): ... - ValueError: face fans are defined only for polytopes containing the origin as an interior point! + ValueError: face fans are defined only for polytopes + containing the origin as an interior point! - sage: Q = Polyhedron(vertices = [[-1, 1/2], [1, -1/2]]) + sage: Q = Polyhedron(vertices=[[-1, 1/2], [1, -1/2]]) sage: Q.contains([0,0]) True sage: FF = Q.face_fan(); FF @@ -760,8 +764,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() # optional - sage.rings.number_field + sage: S.face_fan() # optional - sage.rings.number_field Traceback (most recent call last): ... NotImplementedError: face fan handles only polytopes over the rationals @@ -852,8 +856,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) # optional - sage.rings.number_field + sage: P.barycentric_subdivision() # optional - sage.rings.number_field A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 8 vertices @@ -965,17 +969,19 @@ 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],[-1,-1],[1,-1]], backend='normaliz') # optional - pynormaliz - sage: square.vertices() # optional - pynormaliz + sage: square = Polyhedron(vertices=[[1,1], [-1,1], # optional - pynormaliz + ....: [-1,-1], [1,-1]], + ....: backend='normaliz') + sage: square.vertices() # optional - pynormaliz (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 # optional - sage.groups - sage: conj_reps = aut_square.conjugacy_classes_representatives() # optional - pynormaliz # optional - sage.groups - sage: gens_dict = square.permutations_to_matrices(conj_reps); # optional - pynormaliz # optional - sage.groups - sage: rotation_180 = aut_square([(0,3),(1,2)]) # optional - pynormaliz # optional - sage.groups - sage: rotation_180, gens_dict[rotation_180] # optional - pynormaliz # optional - sage.groups + 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 ( [-1 0 0] [ 0 -1 0] @@ -985,11 +991,12 @@ def permutations_to_matrices(self, conj_class_reps, acting_group=None, additiona This example tests the functionality for additional elements:: sage: C = polytopes.cross_polytope(2) - sage: G = C.restricted_automorphism_group(output='permutation') # optional - sage.groups # optional - sage.rings.real_mpfr - sage: conj_reps = G.conjugacy_classes_representatives() # optional - sage.groups # optional - sage.rings.real_mpfr - sage: add_elt = G([(0, 2, 3, 1)]) # optional - sage.groups # optional - sage.rings.real_mpfr - sage: dict = C.permutations_to_matrices(conj_reps,additional_elts = [add_elt]) # optional - sage.groups # optional - sage.rings.real_mpfr - sage: dict[add_elt] # optional - sage.groups # optional - sage.rings.real_mpfr + 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 + ....: additional_elts=[add_elt]) + sage: dict[add_elt] # optional - sage.groups sage.rings.real_mpfr [ 0 1 0] [-1 0 0] [ 0 0 1] @@ -1048,16 +1055,17 @@ def bounding_box(self, integral=False, integral_hull=False): EXAMPLES:: - sage: Polyhedron([ (1/3,2/3), (2/3, 1/3) ]).bounding_box() + sage: Polyhedron([(1/3,2/3), (2/3, 1/3)]).bounding_box() ((1/3, 1/3), (2/3, 2/3)) - sage: Polyhedron([ (1/3,2/3), (2/3, 1/3) ]).bounding_box(integral=True) + sage: Polyhedron([(1/3,2/3), (2/3, 1/3)]).bounding_box(integral=True) ((0, 0), (1, 1)) - sage: Polyhedron([ (1/3,2/3), (2/3, 1/3) ]).bounding_box(integral_hull=True) + sage: Polyhedron([(1/3,2/3), (2/3, 1/3)]).bounding_box(integral_hull=True) (None, None) - sage: Polyhedron([ (1/3,2/3), (3/3, 4/3) ]).bounding_box(integral_hull=True) + 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 - ((-0.8090169944, -0.8090169944, -0.8090169944), (0.8090169944, 0.8090169944, 0.8090169944)) + sage: polytopes.buckyball(exact=False).bounding_box() # optional - sage.groups + ((-0.8090169944, -0.8090169944, -0.8090169944), + (0.8090169944, 0.8090169944, 0.8090169944)) TESTS:: @@ -1148,25 +1156,25 @@ def _polymake_init_(self): Algebraic polyhedron:: - sage: P = polytopes.dodecahedron(); P # optional - sage.rings.number_field + sage: P = polytopes.dodecahedron(); P # optional - 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("There may be a recompilation warning"); PP = polymake(P); PP # optional - jupymake # optional - sage.rings.number_field - There may be a recompilation warning... + sage: print("Maybe recompile warning"); PP = polymake(P); PP # optional - jupymake sage.rings.number_field + Maybe recompile warning... Polytope>[...] - sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake # optional - sage.rings.number_field + sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake 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 # optional - sage.groups A 3-dimensional polyhedron in RDF^3 defined as the convex hull of 20 vertices - sage: print("There may be a recompilation warning"); PP = polymake(P); PP # optional - jupymake # optional - sage.groups + sage: print("Maybe recompile warning"); PP = polymake(P); PP # optional - jupymake sage.groups There may be a recompilation warning... Polytope[...] - sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake # optional - sage.groups + sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake sage.groups 1 -0.472135955 0 -1.236067978 """ diff --git a/src/sage/geometry/polyhedron/base2.py b/src/sage/geometry/polyhedron/base2.py index ab83971f35f..41ec3ad203d 100644 --- a/src/sage/geometry/polyhedron/base2.py +++ b/src/sage/geometry/polyhedron/base2.py @@ -143,8 +143,9 @@ def lattice_polytope(self, envelope=False): First, a polyhedron with integral vertices:: sage: P = Polyhedron(vertices=[(1, 0), (0, 1), (-1, 0), (0, -1)]) - sage: lp = P.lattice_polytope() - sage: lp # optional - palp + sage: lp = P.lattice_polytope(); lp + 2-d reflexive polytope... in 2-d lattice M + sage: lp # optional - palp polytopes_db 2-d reflexive polytope #3 in 2-d lattice M sage: lp.vertices() M(-1, 0), @@ -163,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 + sage: lp # optional - palp polytopes_db 2-d reflexive polytope #5 in 2-d lattice M sage: lp.vertices() M(-1, 0), diff --git a/src/sage/geometry/polyhedron/base4.py b/src/sage/geometry/polyhedron/base4.py index 30da8c35733..6b309553123 100644 --- a/src/sage/geometry/polyhedron/base4.py +++ b/src/sage/geometry/polyhedron/base4.py @@ -1225,7 +1225,7 @@ def is_self_dual(self): True sage: polytopes.cube().is_self_dual() False - sage: polytopes.hypersimplex(5,2).is_self_dual() + sage: polytopes.hypersimplex(5,2).is_self_dual() # optional - sage.combinat False sage: P = Polyhedron(vertices=[[1/2, 1/3]], rays=[[1, 1]]).is_self_dual() Traceback (most recent call last): diff --git a/src/sage/geometry/polyhedron/base5.py b/src/sage/geometry/polyhedron/base5.py index 311ff1c59fe..decd2fb05a4 100644 --- a/src/sage/geometry/polyhedron/base5.py +++ b/src/sage/geometry/polyhedron/base5.py @@ -164,8 +164,8 @@ def polar(self, in_affine_span=False): EXAMPLES:: - sage: p = Polyhedron(vertices = [[0,0,1],[0,1,0],[1,0,0],[0,0,0],[1,1,1]], base_ring=QQ) - sage: p + sage: p = Polyhedron(vertices=[[0,0,1], [0,1,0], [1,0,0], [0,0,0], [1,1,1]], + ....: base_ring=QQ); p A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 5 vertices sage: p.polar() A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 6 vertices @@ -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() # optional - sage.rings.number_field """ if tester is None: tester = self._tester(**options) @@ -393,8 +393,7 @@ def bipyramid(self): sage: cross_poly_4d = octahedron.bipyramid() sage: cross_poly_4d.n_vertices() 8 - sage: q = [list(v) for v in cross_poly_4d.vertex_generator()] - sage: q + sage: q = [list(v) for v in cross_poly_4d.vertex_generator()]; q [[-1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], @@ -639,11 +638,9 @@ def lawrence_polytope(self): sage: L = P.lawrence_polytope(); L A 9-dimensional polyhedron in ZZ^9 defined as the convex hull of 12 vertices sage: V = P.vertices_list() - sage: i = 0 - sage: for v in V: + sage: for i, v in enumerate(V): ....: v = v + i*[0] ....: P = P.lawrence_extension(v) - ....: i = i + 1 sage: P == L True @@ -699,14 +696,17 @@ def minkowski_sum(self, other): A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 13 vertices sage: four_cube = polytopes.hypercube(4) - sage: four_simplex = Polyhedron(vertices = [[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]]) + sage: four_simplex = Polyhedron(vertices=[[0, 0, 0, 1], [0, 0, 1, 0], + ....: [0, 1, 0, 0], [1, 0, 0, 0]]) sage: four_cube + four_simplex A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 36 vertices sage: four_cube.minkowski_sum(four_simplex) == four_cube + four_simplex True - sage: poly_spam = Polyhedron([[3,4,5,2],[1,0,0,1],[0,0,0,0],[0,4,3,2],[-3,-3,-3,-3]], base_ring=ZZ) - sage: poly_eggs = Polyhedron([[5,4,5,4],[-4,5,-4,5],[4,-5,4,-5],[0,0,0,0]], base_ring=QQ) + sage: poly_spam = Polyhedron([[3,4,5,2], [1,0,0,1], [0,0,0,0], + ....: [0,4,3,2], [-3,-3,-3,-3]], base_ring=ZZ) + sage: poly_eggs = Polyhedron([[5,4,5,4], [-4,5,-4,5], + ....: [4,-5,4,-5], [0,0,0,0]], base_ring=QQ) sage: poly_spam + poly_spam + poly_eggs A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 12 vertices """ @@ -771,7 +771,7 @@ def minkowski_difference(self, other): The polyhedra need not be full-dimensional:: - sage: X2 = Polyhedron(vertices=[(-1,-1,0),(1,-1,0),(-1,1,0),(1,1,0)]) + sage: X2 = Polyhedron(vertices=[(-1,-1,0), (1,-1,0), (-1,1,0), (1,1,0)]) sage: Y2 = Polyhedron(vertices=[(0,0,0), (0,1,0), (1,0,0)]) / 2 sage: (X2+Y2)-Y2 == X2 True @@ -782,7 +782,8 @@ def minkowski_difference(self, other): :: sage: four_cube = polytopes.hypercube(4) - sage: four_simplex = Polyhedron(vertices = [[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]]) + sage: four_simplex = Polyhedron(vertices=[[0, 0, 0, 1], [0, 0, 1, 0], + ....: [0, 1, 0, 0], [1, 0, 0, 0]]) sage: four_cube - four_simplex A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 16 vertices sage: four_cube.minkowski_difference(four_simplex) == four_cube - four_simplex @@ -790,8 +791,10 @@ def minkowski_difference(self, other): Coercion of the base ring works:: - sage: poly_spam = Polyhedron([[3,4,5,2],[1,0,0,1],[0,0,0,0],[0,4,3,2],[-3,-3,-3,-3]], base_ring=ZZ) - sage: poly_eggs = Polyhedron([[5,4,5,4],[-4,5,-4,5],[4,-5,4,-5],[0,0,0,0]], base_ring=QQ) / 100 + sage: poly_spam = Polyhedron([[3,4,5,2], [1,0,0,1], [0,0,0,0], + ....: [0,4,3,2], [-3,-3,-3,-3]], base_ring=ZZ) + sage: poly_eggs = Polyhedron([[5,4,5,4], [-4,5,-4,5], + ....: [4,-5,4,-5], [0,0,0,0]], base_ring=QQ) / 100 sage: poly_spam - poly_eggs A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices @@ -867,7 +870,7 @@ def __sub__(self, other): sage: (X-v)+v == X True - sage: Y = Polyhedron(vertices=[(1/2,0),(0,1/2)]) + sage: Y = Polyhedron(vertices=[(1/2,0), (0,1/2)]) sage: (X-Y).Vrepresentation() (A vertex at (1/2, -1), A vertex at (1/2, 1/2), A vertex at (-1, 1/2), A vertex at (-1, -1)) @@ -893,8 +896,8 @@ def product(self, other): EXAMPLES:: - sage: P1 = Polyhedron([[0],[1]], base_ring=ZZ) - sage: P2 = Polyhedron([[0],[1]], base_ring=QQ) + sage: P1 = Polyhedron([[0], [1]], base_ring=ZZ) + sage: P2 = Polyhedron([[0], [1]], base_ring=QQ) sage: P1.product(P2) A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices @@ -1054,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()) # optional - sage.graphs True sage: P = polytopes.simplex(backend='cdd') @@ -1155,11 +1158,11 @@ def subdirect_sum(self, other): EXAMPLES:: - sage: P1 = Polyhedron([[1],[2]], base_ring=ZZ) - sage: P2 = Polyhedron([[3],[4]], base_ring=QQ) - sage: sds = P1.subdirect_sum(P2);sds - A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 - vertices + sage: P1 = Polyhedron([[1], [2]], base_ring=ZZ) + sage: P2 = Polyhedron([[3], [4]], base_ring=QQ) + sage: sds = P1.subdirect_sum(P2); sds + A 2-dimensional polyhedron in QQ^2 + defined as the convex hull of 4 vertices sage: sds.vertices() (A vertex at (0, 3), A vertex at (0, 4), @@ -1220,8 +1223,8 @@ def direct_sum(self, other): EXAMPLES:: - sage: P1 = Polyhedron([[1],[2]], base_ring=ZZ) - sage: P2 = Polyhedron([[3],[4]], base_ring=QQ) + sage: P1 = Polyhedron([[1], [2]], base_ring=ZZ) + sage: P2 = Polyhedron([[3], [4]], base_ring=QQ) sage: ds = P1.direct_sum(P2);ds A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices sage: ds.vertices() @@ -1297,8 +1300,8 @@ def convex_hull(self, other): sage: a_simplex = polytopes.simplex(3, project=True) sage: verts = a_simplex.vertices() - sage: verts = [[x[0]*3/5+x[1]*4/5, -x[0]*4/5+x[1]*3/5, x[2]] for x in verts] - sage: another_simplex = Polyhedron(vertices = verts) + sage: verts = [[x[0]*3/5 + x[1]*4/5, -x[0]*4/5 + x[1]*3/5, x[2]] for x in verts] + sage: another_simplex = Polyhedron(vertices=verts) sage: simplex_union = a_simplex.convex_hull(another_simplex) sage: simplex_union.n_vertices() 7 @@ -1352,10 +1355,10 @@ 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: 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 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 @@ -1462,15 +1465,15 @@ def translation(self, displacement): EXAMPLES:: - sage: P = Polyhedron([[0,0],[1,0],[0,1]], base_ring=ZZ) + sage: P = Polyhedron([[0,0], [1,0], [0,1]], base_ring=ZZ) sage: P.translation([2,1]) A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices - sage: P.translation( vector(QQ,[2,1]) ) + sage: P.translation(vector(QQ, [2,1])) A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices TESTS:: - sage: P = Polyhedron([[0,0],[1,0],[0,1]], base_ring=ZZ, backend='field') + sage: P = Polyhedron([[0,0], [1,0], [0,1]], base_ring=ZZ, backend='field') sage: P.translation([2,1]).backend() 'field' @@ -1507,7 +1510,7 @@ def _translation_double_description(self, displacement): EXAMPLES:: - sage: P = Polyhedron([[0,0],[1,0],[0,1]], base_ring=ZZ) + sage: P = Polyhedron([[0,0], [1,0], [0,1]], base_ring=ZZ) sage: Vrep, Hrep, parent = P._translation_double_description([2,1]) sage: [tuple(x) for x in Vrep], [tuple(x) for x in Hrep], parent ([((2, 1), (2, 2), (3, 1)), (), ()], @@ -1547,7 +1550,7 @@ def dilation(self, scalar): EXAMPLES:: - sage: p = Polyhedron(vertices = [[t,t^2,t^3] for t in srange(2,6)]) + sage: p = Polyhedron(vertices=[[t,t^2,t^3] for t in srange(2,6)]) sage: next(p.vertex_generator()) A vertex at (2, 4, 8) sage: p2 = p.dilation(2) @@ -1704,35 +1707,43 @@ def linear_transformation(self, linear_transf, new_base_ring=None): EXAMPLES:: sage: b3 = polytopes.Birkhoff_polytope(3) - sage: proj_mat=matrix([[0,1,0,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0],[0,0,0,0,0,1,0,0,0],[0,0,0,0,0,0,0,1,0]]) + sage: proj_mat = matrix([[0,1,0,0,0,0,0,0,0], [0,0,0,1,0,0,0,0,0], + ....: [0,0,0,0,0,1,0,0,0], [0,0,0,0,0,0,0,1,0]]) 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: square = polytopes.regular_polygon(4) # optional - sage.rings.number_field + sage: square.vertices_list() # optional - sage.rings.number_field [[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]]) # optional - sage.rings.number_field + sage: sheared = transf * square # optional - sage.rings.number_field + sage: sheared.vertices_list() # optional - sage.rings.number_field [[-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) # optional - sage.rings.number_field 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 - A 3-dimensional polyhedron in (Number Field in sqrt2sqrt3 with defining polynomial x^4 - 10*x^2 + 1 with sqrt2sqrt3 = 0.3178372451957823?)^3 defined as the convex hull of 8 vertices + 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 + A 3-dimensional polyhedron in + (Number Field in sqrt2sqrt3 with defining polynomial x^4 - 10*x^2 + 1 + with sqrt2sqrt3 = 0.3178372451957823?)^3 + defined as the convex hull of 8 vertices Linear transformation without specified new base ring fails in this case:: - sage: M*P # optional - sage.rings.number_field + sage: M*P # optional - sage.rings.number_field Traceback (most recent call last): ... - TypeError: unsupported operand parent(s) for *: 'Full MatrixSpace of 3 by 3 dense matrices over Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?' and 'Full MatrixSpace of 3 by 8 dense matrices over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?' + TypeError: unsupported operand parent(s) for *: + 'Full MatrixSpace of 3 by 3 dense matrices over Number Field in sqrt3 + with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?' and + 'Full MatrixSpace of 3 by 8 dense matrices over Number Field in sqrt2 + with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?' TESTS: @@ -1749,7 +1760,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 # optional - 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:: @@ -1763,13 +1774,17 @@ def linear_transformation(self, linear_transf, new_base_ring=None): sage: Matrix([[0 for _ in range(8)]]) * b3 Traceback (most recent call last): ... - TypeError: unsupported operand parent(s) for *: 'Full MatrixSpace of 1 by 8 dense matrices over Integer Ring' and 'Full MatrixSpace of 9 by 6 dense matrices over Integer Ring' + TypeError: unsupported operand parent(s) for *: + 'Full MatrixSpace of 1 by 8 dense matrices over Integer Ring' and + 'Full MatrixSpace of 9 by 6 dense matrices over Integer Ring' sage: Matrix(ZZ, []) * b3 A 0-dimensional polyhedron in ZZ^0 defined as the convex hull of 1 vertex sage: Matrix(ZZ, [[],[]]) * b3 Traceback (most recent call last): ... - TypeError: unsupported operand parent(s) for *: 'Full MatrixSpace of 2 by 0 dense matrices over Integer Ring' and 'Full MatrixSpace of 9 by 6 dense matrices over Integer Ring' + TypeError: unsupported operand parent(s) for *: + 'Full MatrixSpace of 2 by 0 dense matrices over Integer Ring' and + 'Full MatrixSpace of 9 by 6 dense matrices over Integer Ring' Check that the precomputed double description is correct:: @@ -1944,7 +1959,7 @@ def face_truncation(self, face, linear_coefficients=None, cut_frac=None): A vertex at (-1, -1/3, -1), A vertex at (-1/3, -1, -1), A vertex at (-1, -1, -1/3)) - sage: vertex_trunc2 = Cube.face_truncation(Cube.faces(0)[0],cut_frac=1/2) + sage: vertex_trunc2 = Cube.face_truncation(Cube.faces(0)[0], cut_frac=1/2) sage: vertex_trunc2.f_vector() (1, 10, 15, 7, 1) sage: tuple(f.ambient_V_indices() for f in vertex_trunc2.faces(2)) @@ -1966,7 +1981,7 @@ def face_truncation(self, face, linear_coefficients=None, cut_frac=None): A vertex at (-1, 0, -1), A vertex at (0, -1, -1), A vertex at (-1, -1, 0)) - sage: vertex_trunc3 = Cube.face_truncation(Cube.faces(0)[0],cut_frac=0.3) + sage: vertex_trunc3 = Cube.face_truncation(Cube.faces(0)[0], cut_frac=0.3) sage: vertex_trunc3.vertices() (A vertex at (-1.0, -1.0, 1.0), A vertex at (-1.0, 1.0, -1.0), @@ -1999,7 +2014,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: face_trunc.face_lattice().is_isomorphic(Cube.face_lattice()) # optional - sage.combinat sage.graphs True TESTS: @@ -2093,20 +2108,20 @@ def stack(self, face, position=None): ... ValueError: cannot stack onto a vertex - sage: stacked_square_half = cube.stack(square_face,position=1/2) + sage: stacked_square_half = cube.stack(square_face, position=1/2) sage: stacked_square_half.f_vector() (1, 9, 16, 9, 1) - sage: stacked_square_large = cube.stack(square_face,position=10) + 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: hexaprism = polytopes.regular_polygon(6).prism() # optional - sage.rings.number_field + sage: hexaprism.f_vector() # optional - sage.rings.number_field (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] # 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 (1, 13, 22, 11, 1) - sage: hexaprism.stack(square_face,position=4) # optional - sage.rings.number_field + sage: hexaprism.stack(square_face, position=4) # optional - sage.rings.number_field Traceback (most recent call last): ... ValueError: the chosen position is too large @@ -2128,7 +2143,7 @@ def stack(self, face, position=None): It is possible to stack on unbounded faces:: - sage: Q = Polyhedron(vertices=[[0,1],[1,0]],rays=[[1,1]]) + sage: Q = Polyhedron(vertices=[[0,1], [1,0]], rays=[[1,1]]) sage: E = Q.faces(1) sage: Q.stack(E[0],1/2).Vrepresentation() (A vertex at (0, 1), @@ -2226,17 +2241,17 @@ 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: 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 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 # optional - sage.rings.number_field + 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 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) # optional - sage.combinat + sage: W2 = Q.wedge(Q.faces(2)[7]); W2 # optional - sage.combinat A 4-dimensional polyhedron in QQ^5 defined as the convex hull of 9 vertices - sage: W2.vertices() # optional - sage.combinat + sage: W2.vertices() # optional - sage.combinat (A vertex at (1, 1, 0, 0, 1), A vertex at (1, 1, 0, 0, -1), A vertex at (1, 0, 1, 0, 1), @@ -2247,9 +2262,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 # optional - sage.combinat A 4-dimensional polyhedron in QQ^5 defined as the convex hull of 10 vertices - sage: W3.vertices() # optional - sage.combinat + sage: W3.vertices() # optional - sage.combinat (A vertex at (1, 1, 0, 0, -2), A vertex at (1, 1, 0, 0, 2), A vertex at (1, 0, 1, 0, -2), @@ -2262,9 +2277,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 # optional - sage.rings.number_field + 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 True REFERENCES: @@ -2348,10 +2363,10 @@ 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: 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 (1, 7, 14, 9, 1) TESTS: @@ -2435,7 +2450,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() # optional - sage.rings.number_field Check that :trac:`30293` is fixed:: @@ -2544,10 +2559,10 @@ 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: 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 (1, 6, 12, 8, 1) It works with a polyhedral face as well:: @@ -2567,7 +2582,9 @@ def one_point_suspension(self, vertex): sage: cube.one_point_suspension(e) Traceback (most recent call last): ... - TypeError: the vertex A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices should be a Vertex or PolyhedronFace of dimension 0 + TypeError: the vertex + A 1-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 2 vertices + should be a Vertex or PolyhedronFace of dimension 0 """ from sage.geometry.polyhedron.representation import Vertex from sage.geometry.polyhedron.face import PolyhedronFace diff --git a/src/sage/geometry/polyhedron/base6.py b/src/sage/geometry/polyhedron/base6.py index 35571185548..e125b5228a0 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) # optional - 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')) # optional - 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) # optional - sage.plot sage: Polyhedron_base6.schlegel_projection(Q) The projection of a polyhedron into 3 dimensions @@ -194,82 +194,84 @@ def plot(self, By default, the wireframe is rendered in blue and the fill in green:: - sage: square.plot() # optional - sage.plot + sage: square.plot() # optional - sage.plot Graphics object consisting of 6 graphics primitives - sage: point.plot() # optional - sage.plot + sage: point.plot() # optional - sage.plot Graphics object consisting of 1 graphics primitive - sage: line.plot() # optional - sage.plot + sage: line.plot() # optional - sage.plot Graphics object consisting of 2 graphics primitives - sage: cube.plot() # optional - sage.plot + sage: cube.plot() # optional - sage.plot Graphics3d Object - sage: hypercube.plot() # optional - sage.plot + sage: hypercube.plot() # optional - sage.plot Graphics3d Object Draw the lines in red and nothing else:: - sage: square.plot(point=False, line='red', polygon=False) # optional - sage.plot + sage: square.plot(point=False, line='red', polygon=False) # optional - sage.plot 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) # optional - sage.plot 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) # optional - sage.plot 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) # optional - sage.plot Graphics3d Object - sage: hypercube.plot(point=False, line='red', polygon=False) # optional - sage.plot + sage: hypercube.plot(point=False, line='red', polygon=False) # optional - sage.plot 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: square.plot(point={'color':'red'}, line=False, polygon=(0,0,1)) # optional - sage.plot 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)) # optional - sage.plot 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)) # optional - sage.plot 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)) # optional - sage.plot 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)) # optional - sage.plot 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: square.plot(fill='green', wireframe='red') # optional - sage.plot Graphics object consisting of 6 graphics primitives - sage: point.plot(fill='green', wireframe='red') # optional - sage.plot + sage: point.plot(fill='green', wireframe='red') # optional - sage.plot Graphics object consisting of 1 graphics primitive - sage: line.plot(fill='green', wireframe='red') # optional - sage.plot + sage: line.plot(fill='green', wireframe='red') # optional - sage.plot Graphics object consisting of 2 graphics primitives - sage: cube.plot(fill='green', wireframe='red') # optional - sage.plot + sage: cube.plot(fill='green', wireframe='red') # optional - sage.plot Graphics3d Object - sage: hypercube.plot(fill='green', wireframe='red') # optional - sage.plot + sage: hypercube.plot(fill='green', wireframe='red') # optional - sage.plot Graphics3d Object It is possible to draw polyhedra up to dimension 4, no matter what the ambient dimension is:: sage: hcube = polytopes.hypercube(5) - sage: facet = hcube.facets()[0].as_polyhedron();facet + 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() # optional - 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') # optional - sage.plot Graphics3d Object - sage: cube.plot(polygon={'color':'rainbow'}) # optional - sage.plot + sage: cube.plot(polygon={'color':'rainbow'}) # optional - sage.plot Graphics3d Object - sage: cube.plot(fill='rainbow') # optional - sage.plot + sage: cube.plot(fill='rainbow') # optional - 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) # optional - sage.plot Graphics3d Object - sage: prism.plot(point={'size':20, 'color':'black'}, line={'thickness':30, 'width':1, 'color':'black'}, polygon='rainbow') # optional - sage.plot + sage: prism.plot(point={'size':20, 'color':'black'}, # optional - sage.plot + ....: line={'thickness':30, 'width':1, 'color':'black'}, + ....: polygon='rainbow') Graphics3d Object TESTS:: @@ -470,7 +472,7 @@ def show(self, **kwds): EXAMPLES:: sage: square = polytopes.hypercube(2) - sage: square.show(point='red') # optional - sage.plot + sage: square.show(point='red') # optional - sage.plot """ self.plot(**kwds).show() @@ -545,8 +547,8 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, EXAMPLES:: 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') # optional - sage.plot + sage: Img # optional - sage.plot \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -563,7 +565,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])) # optional - sage.plot %% with the command: ._tikz_3d_in_3d and parameters: %% view = [0, 0, 1] %% angle = 0 @@ -573,7 +575,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])) # optional - sage.plot %% Coordinate of the vertices: %% \coordinate (-1.00000, -1.00000, 0.00000) at (-1.00000, -1.00000, 0.00000); @@ -582,8 +584,8 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, When output type is a :class:`sage.misc.latex_standalone.TikzPicture`:: 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') # optional - sage.plot + sage: t # optional - sage.plot \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -600,7 +602,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 # optional - sage.plot """ return self.projection().tikz(view, angle, scale, @@ -692,8 +694,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) # optional - sage.groups + sage: sum(P.gale_transform()).norm() < 1e-15 # optional - sage.groups True """ if not self.is_compact(): @@ -784,8 +786,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) # optional - sage.plot + sage: type(p_solid) # optional - sage.plot """ proj = self.projection() @@ -803,8 +805,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() # optional - sage.plot + sage: p_wireframe._objects # optional - sage.plot [Line defined by 2 points, Line defined by 2 points, Line defined by 2 points] """ proj = self.projection() @@ -853,30 +855,30 @@ 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() # optional - 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 # optional - sage.symbolic + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4]) # optional - sage.symbolic + sage: sp.plot() # optional - 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 # optional - sage.symbolic + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 1/2) # optional - sage.symbolic + sage: sp.plot() # optional - sage.plot sage.symbolic Graphics3d Object - sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 4) # optional - sage.symbolic - sage: sp.plot() # optional - sage.plot # optional - sage.symbolic + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 4) # optional - sage.symbolic + sage: sp.plot() # optional - sage.plot sage.symbolic Graphics3d Object A value which is too large give a projection point that sees more than one facet resulting in a error:: - sage: sp = tfcube.schlegel_projection(tfcube.facets()[4],5) + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 5) Traceback (most recent call last): ... ValueError: the chosen position is too large @@ -936,10 +938,11 @@ def _affine_hull_projection(self, *, Check that :trac:`24047` is fixed:: - sage: P1 = Polyhedron(vertices=([[-1, 1], [0, -1], [0, 0], [-1, -1]])) + 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, orthonormal=True, extend=True) # optional - sage.rings.number_field + sage: A, b = P.affine_hull_projection(as_affine_map=True, # optional - sage.rings.number_field + ....: orthonormal=True, extend=True) sage: Polyhedron([(2,3,4)]).affine_hull_projection() A 0-dimensional polyhedron in ZZ^0 defined as the convex hull of 1 vertex @@ -950,27 +953,26 @@ 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, extend=True).backend() # optional - sage.rings.number_field + sage: P.affine_hull_projection(orthogonal=True, orthonormal=True, # optional - sage.rings.number_field + ....: extend=True).backend() 'field' Check that :trac:`29116` is fixed:: - sage: V =[ - ....: [1, 0, -1, 0, 0], - ....: [1, 0, 0, -1, 0], - ....: [1, 0, 0, 0, -1], - ....: [1, 0, 0, +1, 0], - ....: [1, 0, 0, 0, +1], - ....: [1, +1, 0, 0, 0] - ....: ] + sage: V = [[1, 0, -1, 0, 0], + ....: [1, 0, 0, -1, 0], + ....: [1, 0, 0, 0, -1], + ....: [1, 0, 0, +1, 0], + ....: [1, 0, 0, 0, +1], + ....: [1, +1, 0, 0, 0]] 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) # optional - 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) # optional - sage.rings.number_field A 4-dimensional polyhedron in AA^4 defined as the convex hull of 6 vertices """ result = AffineHullProjectionData() @@ -1176,7 +1178,7 @@ def affine_hull_projection(self, The resulting affine hulls depend on the parameter ``orthogonal`` and ``orthonormal``:: - sage: L = Polyhedron([[1,0],[0,1]]); L + sage: L = Polyhedron([[1,0], [0,1]]); L A 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices sage: A = L.affine_hull_projection(); A A 1-dimensional polyhedron in ZZ^1 defined as the convex hull of 2 vertices @@ -1186,13 +1188,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) # optional - 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 # optional - 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() # optional - sage.rings.number_field (A vertex at (1.414213562373095?), A vertex at (0.?e-18)) More generally:: @@ -1218,9 +1220,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 # optional - 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() # optional - 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), @@ -1229,81 +1231,102 @@ def affine_hull_projection(self, With the parameter ``minimal`` one can get a minimal base ring:: 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) # optional - sage.rings.number_field + sage: s_AA.base_ring() # optional - sage.rings.number_field Algebraic Real Field - sage: s_full = s.affine_hull_projection(orthonormal=True, extend=True, minimal=True) # optional - sage.rings.number_field - sage: s_full.base_ring() # optional - sage.rings.number_field - Number Field in a with defining polynomial y^4 - 4*y^2 + 1 with a = 0.5176380902050415? + sage: s_full = s.affine_hull_projection(orthonormal=True, extend=True, # optional - sage.rings.number_field + ....: minimal=True) + sage: s_full.base_ring() # optional - sage.rings.number_field + 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 # optional - sage.rings.number_field + sage: P = polytopes.permutahedron(3); P # optional - sage.combinat sage.rings.number_field A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices - sage: set([F.as_polyhedron().affine_hull_projection(orthonormal=True, extend=True).volume() for F in P.affine_hull_projection().faces(1)]) == {1, sqrt(AA(2))} # optional - sage.combinat # optional - sage.rings.number_field + sage: set([F.as_polyhedron().affine_hull_projection( # optional - 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(orthonormal=True, extend=True).volume() for F in P.affine_hull_projection(orthonormal=True, extend=True).faces(1)]) == {sqrt(AA(2))} # optional - sage.combinat # optional - sage.rings.number_field + sage: set([F.as_polyhedron().affine_hull_projection( # optional - 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 - 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: 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 + 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 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 - 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: K. = QuadraticField(2) # optional - sage.rings.number_field + sage: P = Polyhedron([2*[K.zero()],2*[sqrt2]]); P # optional - sage.rings.number_field + 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 (A vertex at (0, 0), A vertex at (sqrt2, sqrt2)) - sage: A = P.affine_hull_projection(orthonormal=True); A # optional - sage.rings.number_field - 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 = P.affine_hull_projection(orthonormal=True); A # optional - sage.rings.number_field + 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 (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 - 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: K. = QuadraticField(3) # optional - sage.rings.number_field + sage: P = Polyhedron([2*[K.zero()], 2*[sqrt3]]); P # optional - sage.rings.number_field + 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 (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) # optional - sage.rings.number_field 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 # optional - 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() # optional - sage.rings.number_field (A vertex at (0), A vertex at (2.449489742783178?)) - sage: sqrt(6).n() # optional - sage.rings.number_field + sage: sqrt(6).n() # optional - sage.rings.number_field 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()) # optional - sage.rings.number_field True - sage: P.is_combinatorially_isomorphic(P.affine_hull_projection(orthogonal=True)) # optional - sage.rings.number_field + sage: P.is_combinatorially_isomorphic(P.affine_hull_projection( # optional - sage.rings.number_field + ....: orthogonal=True)) True - sage: P.is_combinatorially_isomorphic(P.affine_hull_projection(orthonormal=True, extend=True)) # optional - sage.rings.number_field + sage: P.is_combinatorially_isomorphic(P.affine_hull_projection( # optional - 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: 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 (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() # optional - sage.rings.number_field + sage: p = polytopes.regular_polygon(5) # optional - sage.rings.number_field + sage: p.volume() # optional - sage.rings.number_field 2.377641290737884? - sage: P.volume() # optional - sage.rings.number_field + sage: P.volume() # optional - sage.rings.number_field 1.53406271079097? - sage: p.volume()*circumradius^2 # optional - sage.rings.number_field + sage: p.volume()*circumradius^2 # optional - sage.rings.number_field 1.534062710790965? - sage: P.volume() == p.volume()*circumradius^2 # optional - sage.rings.number_field + sage: P.volume() == p.volume()*circumradius^2 # optional - sage.rings.number_field True One can also use ``orthogonal`` parameter to calculate volumes; @@ -1311,28 +1334,31 @@ 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, extend=True) # optional - sage.rings.number_field - sage: Pgonal = Pentagon.affine_hull_projection(orthogonal=True) # optional - sage.rings.number_field - sage: A, b = Pentagon.affine_hull_projection(orthogonal=True, as_affine_map=True) # optional - sage.rings.number_field - sage: Adet = (A.matrix().transpose()*A.matrix()).det() # optional - sage.rings.number_field - sage: Pnormal.volume() # optional - sage.rings.number_field + 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 + ....: 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 + ....: 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 1.53406271079097? - sage: Pgonal.volume()/Adet.sqrt(extend=True) # optional - sage.rings.number_field + sage: Pgonal.volume()/Adet.sqrt(extend=True) # optional - sage.rings.number_field -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) # optional - sage.rings.number_field 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) # optional - sage.rings.number_field True Another example with ``as_affine_map=True``:: - sage: P = polytopes.permutahedron(4) # optional - sage.combinat # optional - sage.rings.number_field - sage: A, b = P.affine_hull_projection(orthonormal=True, as_affine_map=True, extend=True) # optional - sage.combinat # optional - sage.rings.number_field - sage: Q = P.affine_hull_projection(orthonormal=True, extend=True) # optional - sage.combinat # optional - sage.rings.number_field - sage: Q.center() # optional - sage.combinat # optional - sage.rings.number_field + 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 + ....: as_affine_map=True) + sage: Q.center() # optional - sage.combinat sage.rings.number_field (0.7071067811865475?, 1.224744871391589?, 1.732050807568878?) - sage: A(P.center()) + b == Q.center() # optional - sage.combinat # optional - sage.rings.number_field + sage: A(P.center()) + b == Q.center() # optional - sage.combinat sage.rings.number_field True For unbounded, non full-dimensional polyhedra, the ``orthogonal=True`` and ``orthonormal=True`` @@ -1347,11 +1373,13 @@ def affine_hull_projection(self, sage: P.affine_hull_projection(orthogonal=True) Traceback (most recent call last): ... - NotImplementedError: "orthogonal=True" and "orthonormal=True" work only for compact polyhedra + NotImplementedError: "orthogonal=True" and "orthonormal=True" + work only for compact polyhedra sage: P.affine_hull_projection(orthonormal=True) Traceback (most recent call last): ... - NotImplementedError: "orthogonal=True" and "orthonormal=True" work only for compact polyhedra + NotImplementedError: "orthogonal=True" and "orthonormal=True" + work only for compact polyhedra Setting ``as_affine_map`` to ``True`` without ``orthogonal`` or ``orthonormal`` set to ``True``:: @@ -1387,12 +1415,12 @@ def affine_hull_projection(self, ....: as_polyhedron=True, ....: as_affine_map=True); data AffineHullProjectionData(image=A 2-dimensional polyhedron in QQ^2 - defined as the convex hull of 3 vertices, + defined as the convex hull of 3 vertices, projection_linear_map=Vector space morphism represented by the matrix: [ -1 -1/2] [ 1 -1/2] [ 0 1] - Domain: Vector space of dimension 3 over Rational Field + Domain: Vector space of dimension 3 over Rational Field Codomain: Vector space of dimension 2 over Rational Field, projection_translation=(1, 1/2), section_linear_map=None, @@ -1402,42 +1430,47 @@ def affine_hull_projection(self, sage: data = S.affine_hull_projection(orthogonal=True, return_all_data=True); data AffineHullProjectionData(image=A 2-dimensional polyhedron in QQ^2 - defined as the convex hull of 3 vertices, + defined as the convex hull of 3 vertices, projection_linear_map=Vector space morphism represented by the matrix: [ -1 -1/2] [ 1 -1/2] [ 0 1] - Domain: Vector space of dimension 3 over Rational Field + Domain: Vector space of dimension 3 over Rational Field Codomain: Vector space of dimension 2 over Rational Field, projection_translation=(1, 1/2), section_linear_map=Vector space morphism represented by the matrix: [-1/2 1/2 0] [-1/3 -1/3 2/3] - Domain: Vector space of dimension 2 over Rational Field - Codomain: Vector space of dimension 3 over Rational Field, section_translation=(1, 0, 0)) + Domain: Vector space of dimension 2 over Rational Field + Codomain: Vector space of dimension 3 over Rational Field, + section_translation=(1, 0, 0)) The section map is a right inverse of the projection map:: - sage: data.image.linear_transformation(data.section_linear_map.matrix().transpose()) + data.section_translation == S + sage: mat = data.section_linear_map.matrix().transpose() + sage: data.image.linear_transformation(mat) + data.section_translation == S True Same without ``orthogonal=True``:: sage: data = S.affine_hull_projection(return_all_data=True); data AffineHullProjectionData(image=A 2-dimensional polyhedron in ZZ^2 - defined as the convex hull of 3 vertices, + defined as the convex hull of 3 vertices, projection_linear_map=Vector space morphism represented by the matrix: [1 0] [0 1] [0 0] - Domain: Vector space of dimension 3 over Rational Field - Codomain: Vector space of dimension 2 over Rational Field, projection_translation=(0, 0), + Domain: Vector space of dimension 3 over Rational Field + Codomain: Vector space of dimension 2 over Rational Field, + projection_translation=(0, 0), section_linear_map=Vector space morphism represented by the matrix: [ 1 0 -1] [ 0 1 -1] - Domain: Vector space of dimension 2 over Rational Field - Codomain: Vector space of dimension 3 over Rational Field, section_translation=(0, 0, 1)) - sage: data.image.linear_transformation(data.section_linear_map.matrix().transpose()) + data.section_translation == S + Domain: Vector space of dimension 2 over Rational Field + Codomain: Vector space of dimension 3 over Rational Field, + section_translation=(0, 0, 1)) + sage: mat = data.section_linear_map.matrix().transpose() + sage: data.image.linear_transformation(mat) + data.section_translation == S True :: @@ -1473,8 +1506,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() # optional - sage.rings.number_field + sage: D.facets()[0].as_polyhedron()._test_affine_hull_projection() # optional - sage.rings.number_field """ if tester is None: tester = self._tester(**options) @@ -1564,42 +1597,48 @@ def affine_hull_manifold(self, name=None, latex_name=None, start_index=0, ambien 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 # optional - 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() # optional - sage.symbolic 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() # optional - sage.symbolic E^3 → A (x, y, z) ↦ (x0, x1) = (x, y) - sage: A.adapted_chart() # optional - sage.symbolic + sage: A.adapted_chart() # optional - sage.symbolic [Chart (E^3, (x0_E3, x1_E3, t0_E3))] - sage: A.normal().display() # optional - sage.symbolic + sage: A.normal().display() # optional - sage.symbolic 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 - Riemannian metric gamma on the 2-dimensional Riemannian submanifold A embedded in the Euclidean space E^3 - sage: A.volume_form() # optional - sage.symbolic - 2-form eps_gamma on the 2-dimensional Riemannian submanifold A embedded in the Euclidean space E^3 + sage: A.induced_metric() # Need to call this before volume_form # optional - sage.symbolic + Riemannian metric gamma on the + 2-dimensional Riemannian submanifold A embedded in the Euclidean space E^3 + sage: A.volume_form() # optional - sage.symbolic + 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 # optional - 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() # optional - 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 + (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 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 # optional - sage.symbolic - sage: submanifolds = [ # long time # optional - sage.rings.number_field # optional - sage.symbolic - ....: F.as_polyhedron().affine_hull_manifold(name=f'F{i}', orthogonal=True, ambient_space=E3) + 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 + ....: 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({}, srange(-2, 2, 0.1), srange(-2, 2, 0.1), opacity=0.2) # not tested # long time # optional - sage.symbolic # optional - sage.plot # optional - sage.rings.number_field + sage: sum(FM.plot({}, # not tested # long time # optional - sage.symbolic sage.plot sage.rings.number_field + ....: srange(-2, 2, 0.1), srange(-2, 2, 0.1), + ....: opacity=0.2) ....: for FM in submanifolds) + D.plot() Graphics3d Object @@ -1607,7 +1646,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() # optional - sage.symbolic Euclidean space E^3 """ diff --git a/src/sage/geometry/polyhedron/base7.py b/src/sage/geometry/polyhedron/base7.py index 3465f22875d..2f1fb4cf45e 100644 --- a/src/sage/geometry/polyhedron/base7.py +++ b/src/sage/geometry/polyhedron/base7.py @@ -44,15 +44,15 @@ class Polyhedron_base7(Polyhedron_base6): TESTS:: 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]) # optional - sage.combinat + sage: Polyhedron_base7.centroid(P) # optional - sage.combinat (81/632, 36/79, 81/632) - sage: Polyhedron_base7.triangulate(P) # optional - sage.combinat + sage: Polyhedron_base7.triangulate(P) # optional - sage.combinat (<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') # optional - sage.combinat 79/3 """ @cached_method(do_pickle=True) @@ -91,12 +91,12 @@ 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]) # optional - sage.combinat + sage: P.centroid() # optional - sage.combinat (2/21, 2/21) - sage: P = polytopes.permutahedron(4, backend='normaliz') # optional - pynormaliz - sage: P.centroid() # optional - pynormaliz + sage: P = polytopes.permutahedron(4, backend='normaliz') # optional - pynormaliz + sage: P.centroid() # optional - pynormaliz (5/2, 5/2, 5/2, 5/2) The method is not implemented for unbounded polyhedra:: @@ -226,12 +226,12 @@ def triangulate(self, engine='auto', connected=True, fine=False, regular=None, s sage: cube = polytopes.hypercube(3) sage: triangulation = cube.triangulate( - ....: engine='internal') # to make doctest independent of TOPCOM + ....: engine='internal') # to make doctest independent of TOPCOM sage: triangulation (<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: simplex_indices = triangulation[0]; simplex_indices (0, 1, 2, 7) - sage: simplex_vertices = [ cube.Vrepresentation(i) for i in simplex_indices ] + sage: simplex_vertices = [cube.Vrepresentation(i) for i in simplex_indices] sage: simplex_vertices [A vertex at (1, -1, -1), A vertex at (1, 1, -1), @@ -243,11 +243,14 @@ def triangulate(self, engine='auto', connected=True, fine=False, regular=None, s It is possible to use ``'normaliz'`` as an engine. For this, the polyhedron should have the backend set to normaliz:: - sage: P = Polyhedron(vertices=[[0,0,1],[1,0,1],[0,1,1],[1,1,1]],backend='normaliz') # optional - pynormaliz - sage: P.triangulate(engine='normaliz') # optional - pynormaliz + sage: P = Polyhedron(vertices=[[0,0,1], [1,0,1], # optional - pynormaliz + ....: [0,1,1], [1,1,1]], + ....: backend='normaliz') + sage: P.triangulate(engine='normaliz') # optional - pynormaliz (<0,1,2>, <1,2,3>) - sage: P = Polyhedron(vertices=[[0,0,1],[1,0,1],[0,1,1],[1,1,1]]) + sage: P = Polyhedron(vertices=[[0,0,1], [1,0,1], + ....: [0,1,1], [1,1,1]]) sage: P.triangulate(engine='normaliz') Traceback (most recent call last): ... @@ -255,17 +258,23 @@ 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],[0,1,1],[1,1,1]],backend='normaliz') # optional - pynormaliz - sage: C1.triangulate(engine='normaliz') # optional - pynormaliz + sage: C1 = Polyhedron(rays=[[0,0,1], [1,0,1], # optional - pynormaliz + ....: [0,1,1], [1,1,1]], + ....: backend='normaliz') + sage: C1.triangulate(engine='normaliz') # optional - pynormaliz (<0,1,2>, <1,2,3>) - sage: C2 = Polyhedron(rays=[[1,0,1],[0,0,1],[0,1,1],[1,1,10/9]],backend='normaliz') # optional - pynormaliz - sage: C2.triangulate(engine='normaliz') # optional - pynormaliz + sage: C2 = Polyhedron(rays=[[1,0,1], [0,0,1], # optional - pynormaliz + ....: [0,1,1], [1,1,10/9]], + ....: backend='normaliz') + sage: C2.triangulate(engine='normaliz') # optional - pynormaliz (<0,1,2>, <1,2,3>) They can also be affine cones:: - sage: K = Polyhedron(vertices=[[1,1,1]],rays=[[1,0,0],[0,1,0],[1,1,-1],[1,1,1]], backend='normaliz') # optional - pynormaliz - sage: K.triangulate(engine='normaliz') # optional - pynormaliz + sage: K = Polyhedron(vertices=[[1,1,1]], # optional - pynormaliz + ....: rays=[[1,0,0], [0,1,0], [1,1,-1], [1,1,1]], + ....: backend='normaliz') + sage: K.triangulate(engine='normaliz') # optional - pynormaliz (<0,1,2>, <0,1,3>) """ if self.lines(): @@ -309,11 +318,11 @@ def _volume_lrs(self, verbose=False): EXAMPLES:: - sage: polytopes.hypercube(3)._volume_lrs() # optional - lrslib + sage: polytopes.hypercube(3)._volume_lrs() # optional - lrslib 8 - sage: (polytopes.hypercube(3)*2)._volume_lrs() # optional - lrslib + sage: (polytopes.hypercube(3)*2)._volume_lrs() # optional - lrslib 64 - sage: polytopes.twenty_four_cell()._volume_lrs() # optional - lrslib + sage: polytopes.twenty_four_cell()._volume_lrs() # optional - lrslib 2 REFERENCES: @@ -380,35 +389,35 @@ def _volume_latte(self, verbose=False, algorithm='triangulate', **kwargs): EXAMPLES:: - sage: polytopes.hypercube(3)._volume_latte() # optional - latte_int + sage: polytopes.hypercube(3)._volume_latte() # optional - latte_int 8 - sage: (polytopes.hypercube(3)*2)._volume_latte() # optional - latte_int + sage: (polytopes.hypercube(3)*2)._volume_latte() # optional - latte_int 64 - sage: polytopes.twenty_four_cell()._volume_latte() # optional - latte_int + sage: polytopes.twenty_four_cell()._volume_latte() # optional - latte_int 2 - sage: polytopes.cuboctahedron()._volume_latte() # optional - latte_int + sage: polytopes.cuboctahedron()._volume_latte() # optional - latte_int 20/3 TESTS: Testing triangulate algorithm:: - sage: polytopes.cuboctahedron()._volume_latte(algorithm='triangulate') # optional - latte_int + sage: polytopes.cuboctahedron()._volume_latte(algorithm='triangulate') # optional - latte_int 20/3 Testing cone decomposition algorithm:: - sage: polytopes.cuboctahedron()._volume_latte(algorithm='cone-decompose') # optional - latte_int + sage: polytopes.cuboctahedron()._volume_latte(algorithm='cone-decompose') # optional - latte_int 20/3 Testing raw output:: - sage: polytopes.cuboctahedron()._volume_latte(raw_output=True) # optional - latte_int + sage: polytopes.cuboctahedron()._volume_latte(raw_output=True) # optional - latte_int '20/3' Testing inexact rings:: - sage: P = Polyhedron(vertices=[[0,0],[1,0],[0,1]],base_ring=RDF) + sage: P = Polyhedron(vertices=[[0,0], [1,0], [0,1]],base_ring=RDF) sage: P.volume(engine='latte') Traceback (most recent call last): ... @@ -444,7 +453,7 @@ def _volume_normaliz(self, measure='induced'): TESTS:: - sage: P = Polyhedron(vertices=[[0,0],[1,0],[0,1],[1,1]]) + sage: P = Polyhedron(vertices=[[0,0], [1,0], [0,1], [1,1]]) sage: P._volume_normaliz() Traceback (most recent call last): ... @@ -497,21 +506,21 @@ def volume(self, measure='ambient', engine='auto', **kwds): (which requires a rational polytope):: sage: I3 = polytopes.hypercube(3) - sage: I3.volume(engine='lrs') # optional - lrslib + sage: I3.volume(engine='lrs') # optional - lrslib 8 sage: C24 = polytopes.twenty_four_cell() - sage: C24.volume(engine='lrs') # optional - lrslib + sage: C24.volume(engine='lrs') # optional - lrslib 2 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) # optional - sage.rings.number_field + sage: P5.volume() # optional - sage.rings.number_field 2.377641290737884? - sage: polytopes.icosahedron().volume() # optional - sage.rings.number_field + sage: polytopes.icosahedron().volume() # optional - 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 # optional - sage.rings.number_field 2.18169499062491 When considering lower-dimensional polytopes, we can ask for the @@ -524,83 +533,92 @@ 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') # optional - sage.rings.number_field 1.414213562373095? - sage: P.volume(measure='induced_rational') # optional -- latte_int + sage: P.volume(measure='induced_rational') # optional - latte_int 1 - sage: S = polytopes.regular_polygon(6); S # optional - sage.rings.number_field + sage: S = polytopes.regular_polygon(6); S # optional - sage.rings.number_field 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() # optional - sage.rings.number_field + sage: edge.vertices() # optional - sage.rings.number_field (A vertex at (0.866025403784439?, 1/2), A vertex at (0, 1)) - sage: edge.volume() # optional - sage.rings.number_field + sage: edge.volume() # optional - sage.rings.number_field 0 - sage: edge.volume(measure='induced') # optional - sage.rings.number_field + sage: edge.volume(measure='induced') # optional - sage.rings.number_field 1 - sage: P = Polyhedron(backend='normaliz',vertices=[[1,0,0],[0,0,1],[-1,1,1],[-1,2,0]]) # optional - pynormaliz - sage: P.volume() # optional - pynormaliz + sage: P = Polyhedron(backend='normaliz', # optional - pynormaliz + ....: vertices=[[1,0,0], [0,0,1], + ....: [-1,1,1], [-1,2,0]]) + sage: P.volume() # optional - pynormaliz 0 - sage: P.volume(measure='induced') # optional - pynormaliz # optional - sage.rings.number_field + sage: P.volume(measure='induced') # optional - pynormaliz sage.rings.number_field 2.598076211353316? - sage: P.volume(measure='induced',engine='normaliz') # optional - pynormaliz + sage: P.volume(measure='induced', engine='normaliz') # optional - pynormaliz 2.598076211353316 - sage: P.volume(measure='induced_rational') # optional - pynormaliz, latte_int + sage: P.volume(measure='induced_rational') # optional - pynormaliz latte_int 3/2 - sage: P.volume(measure='induced_rational',engine='normaliz') # optional - pynormaliz + sage: P.volume(measure='induced_rational', # optional - pynormaliz + ....: engine='normaliz') 3/2 - sage: P.volume(measure='induced_lattice') # optional - pynormaliz + sage: P.volume(measure='induced_lattice') # optional - pynormaliz 3 The same polytope without normaliz backend:: - sage: P = Polyhedron(vertices=[[1,0,0],[0,0,1],[-1,1,1],[-1,2,0]]) - sage: P.volume(measure='induced_lattice',engine='latte') # optional - latte_int + sage: P = Polyhedron(vertices=[[1,0,0], [0,0,1], [-1,1,1], [-1,2,0]]) + sage: P.volume(measure='induced_lattice', engine='latte') # optional - latte_int 3 - sage: Dexact = polytopes.dodecahedron() # optional - sage.rings.number_field # optional - sage.groups - sage: v = Dexact.faces(2)[0].as_polyhedron().volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field # optional - sage.groups + sage: Dexact = polytopes.dodecahedron() # optional - sage.rings.number_field sage.groups + sage: F0 = Dexact.faces(2)[0].as_polyhedron() + sage: v = F0.volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field sage.groups 1.53406271079097? - sage: v = Dexact.faces(2)[4].as_polyhedron().volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field # optional - sage.groups + sage: F4 = Dexact.faces(2)[4].as_polyhedron() + sage: v = F4.volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field sage.groups 1.53406271079097? - sage: RDF(v) # abs tol 1e-9 # optional - sage.rings.number_field # optional - sage.groups + sage: RDF(v) # abs tol 1e-9 # optional - sage.rings.number_field sage.groups 1.53406271079044 - sage: Dinexact = polytopes.dodecahedron(exact=False) # optional - sage.groups - sage: w = Dinexact.faces(2)[2].as_polyhedron().volume(measure='induced', engine='internal'); RDF(w) # abs tol 1e-9 # optional - sage.groups + sage: Dinexact = polytopes.dodecahedron(exact=False) # optional - sage.groups + sage: F2 = Dinexact.faces(2)[2].as_polyhedron() + sage: w = F2.volume(measure='induced', engine='internal') # abs tol 1e-9 # optional - sage.groups + sage: RDF(w) 1.5340627082974878 - sage: [polytopes.simplex(d).volume(measure='induced') for d in range(1,5)] == [sqrt(d+1)/factorial(d) for d in range(1,5)] # optional - sage.rings.number_field + sage: all(polytopes.simplex(d).volume(measure='induced') # optional - 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') # optional - sage.rings.number_field 9.48683298050514? - sage: I.volume(measure='induced_rational') # optional -- latte_int + 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') # optional - sage.rings.number_field 13.86542462386205? - sage: T.volume(measure='induced_rational') # optional -- latte_int + sage: T.volume(measure='induced_rational') # optional - latte_int 1/2 sage: Q = Polyhedron(vertices=[(0, 0, 1, 1), (0, 1, 1, 0), (1, 1, 0, 0)]) sage: Q.volume(measure='induced') 1 - sage: Q.volume(measure='induced_rational') # optional -- latte_int + sage: Q.volume(measure='induced_rational') # optional - latte_int 1/2 The volume of a full-dimensional unbounded polyhedron is infinity:: - sage: P = Polyhedron(vertices = [[1, 0], [0, 1]], rays = [[1, 1]]) + sage: P = Polyhedron(vertices=[[1, 0], [0, 1]], rays=[[1, 1]]) sage: P.volume() +Infinity The volume of a non full-dimensional unbounded polyhedron depends on the measure used:: - sage: P = Polyhedron(ieqs = [[1,1,1],[-1,-1,-1],[3,1,0]]); P + sage: P = Polyhedron(ieqs = [[1,1,1], [-1,-1,-1], [3,1,0]]); P A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 ray sage: P.volume() 0 @@ -608,9 +626,9 @@ def volume(self, measure='ambient', engine='auto', **kwds): +Infinity sage: P.volume(measure='ambient') 0 - sage: P.volume(measure='induced_rational') # optional - pynormaliz + 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') # optional - latte_int +Infinity The volume in `0`-dimensional space is taken by counting measure:: @@ -638,7 +656,7 @@ def volume(self, measure='ambient', engine='auto', **kwds): Induced volumes work with lrs (:trac:`33410`):: sage: P = Polyhedron([[0, 0], [1, 1]]) - sage: P.volume(measure='induced', engine='lrs') # optional - lrslib + sage: P.volume(measure='induced', engine='lrs') # optional - lrslib 1.414213562373095? """ from sage.features import FeatureNotPresentError @@ -776,7 +794,7 @@ def integrate(self, function, measure='ambient', **kwds): sage: P = polytopes.cube() sage: x, y, z = polygens(QQ, 'x, y, z') - sage: P.integrate(x^2*y^2*z^2) # optional - latte_int + sage: P.integrate(x^2*y^2*z^2) # optional - latte_int 8/27 If the polyhedron has floating point coordinates, an inexact result can @@ -784,41 +802,45 @@ def integrate(self, function, measure='ambient', **kwds): sage: P = 1.4142*polytopes.cube() sage: P_QQ = Polyhedron(vertices=[[QQ(vi) for vi in v] for v in P.vertex_generator()]) - sage: RDF(P_QQ.integrate(x^2*y^2*z^2)) # optional - latte_int + sage: RDF(P_QQ.integrate(x^2*y^2*z^2)) # optional - latte_int 6.703841212195228 Integral over a non full-dimensional polytope:: 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 = Polyhedron(vertices=[[0,0], [1,1]]) + sage: P.integrate(x*y) # optional - latte_int 0 - sage: ixy = P.integrate(x*y, measure='induced'); ixy # optional - latte_int + sage: ixy = P.integrate(x*y, measure='induced'); ixy # optional - latte_int 0.4714045207910317? - sage: ixy.parent() # optional - latte_int + sage: ixy.parent() # optional - latte_int Algebraic Real Field Convert to a symbolic expression:: - sage: ixy.radical_expression() # optional - latte_int + sage: ixy.radical_expression() # optional - latte_int 1/3*sqrt(2) Another non full-dimensional polytope integration:: sage: R. = QQ[] sage: P = polytopes.simplex(2) - sage: V = AA(P.volume(measure='induced')); V.radical_expression() # optional - sage.rings.number_field sage.symbolic + sage: V = AA(P.volume(measure='induced')) # optional - sage.rings.number_field + sage: V.radical_expression() # optional - sage.rings.number_field sage.symbolic 1/2*sqrt(3) - sage: P.integrate(R(1), measure='induced') == V # optional - latte_int # optional - sage.rings.number_field sage.symbolic + sage: P.integrate(R(1), measure='induced') == V # optional - latte_int sage.rings.number_field sage.symbolic True Computing the mass center:: - sage: (P.integrate(x, measure='induced') / V).radical_expression() # optional - latte_int + sage: (P.integrate(x, measure='induced') # optional - latte_int sage.rings.number_field sage.symbolic + ....: / V).radical_expression() 1/3 - sage: (P.integrate(y, measure='induced') / V).radical_expression() # optional - latte_int + sage: (P.integrate(y, measure='induced') # optional - latte_int sage.rings.number_field sage.symbolic + ....: / V).radical_expression() 1/3 - sage: (P.integrate(z, measure='induced') / V).radical_expression() # optional - latte_int + sage: (P.integrate(z, measure='induced') # optional - latte_int sage.rings.number_field sage.symbolic + ....: / V).radical_expression() 1/3 TESTS: @@ -827,28 +849,28 @@ def integrate(self, function, measure='ambient', **kwds): sage: P = polytopes.octahedron() sage: x, y, z = polygens(QQ, 'x, y, z') - sage: P.integrate(2*x^2*y^4*z^6+z^2) # optional - latte_int + sage: P.integrate(2*x^2*y^4*z^6 + z^2) # optional - latte_int 630632/4729725 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 # optional - sage.rings.number_field + 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 Traceback (most recent call last): ... TypeError: the base ring must be ZZ, QQ, or RDF Testing a univariate polynomial:: - sage: P = Polyhedron(vertices=[[0],[1]]) + sage: P = Polyhedron(vertices=[[0], [1]]) sage: x = polygen(QQ, 'x') - sage: P.integrate(x) # optional - latte_int + sage: P.integrate(x) # optional - latte_int 1/2 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 = Polyhedron(vertices=[[0, 0], [1, 0], [1.1, 1.1], [0, 1]]) + sage: P.integrate('[[1,[2,2]]]') # optional - latte_int Traceback (most recent call last): ... TypeError: LattE integrale cannot be applied over inexact rings @@ -945,7 +967,7 @@ def _integrate_latte_(self, polynomial, **kwds): sage: P = polytopes.cube() sage: x, y, z = polygens(QQ, 'x, y, z') - sage: P._integrate_latte_(x^2 + y^2*z^2) # optional - latte_int + sage: P._integrate_latte_(x^2 + y^2*z^2) # optional - latte_int 32/9 :: diff --git a/src/sage/geometry/polyhedron/base_QQ.py b/src/sage/geometry/polyhedron/base_QQ.py index 0c1cec7fedf..51fd9742159 100644 --- a/src/sage/geometry/polyhedron/base_QQ.py +++ b/src/sage/geometry/polyhedron/base_QQ.py @@ -115,13 +115,13 @@ def integral_points_count(self, verbose=False, use_Hrepresentation=False, sage: P = polytopes.cube() sage: P.integral_points_count() 27 - sage: P.integral_points_count(explicit_enumeration_threshold=0) # optional - latte_int + sage: P.integral_points_count(explicit_enumeration_threshold=0) # optional - latte_int 27 We enlarge the polyhedron to force the use of the generating function methods implemented in LattE integrale, rather than explicit enumeration:: - sage: (1000000000*P).integral_points_count(verbose=True) # optional - latte_int + sage: (1000000000*P).integral_points_count(verbose=True) # optional - latte_int This is LattE integrale... ... Total time:... @@ -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) # optional - latte_int 1 Unbounded polyhedra (with or without lattice points) are not supported:: @@ -291,50 +291,54 @@ 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: poly = simplex.ehrhart_polynomial(engine='latte') # optional - latte_int - sage: poly # optional - latte_int + sage: poly = simplex.ehrhart_polynomial(engine='latte') # optional - latte_int + sage: poly # optional - latte_int 7/2*t^3 + 2*t^2 - 1/2*t + 1 - sage: poly(1) # optional - latte_int + sage: poly(1) # optional - latte_int 6 - sage: len(simplex.integral_points()) # optional - latte_int + sage: len(simplex.integral_points()) # optional - latte_int 6 - sage: poly(2) # optional - latte_int + sage: poly(2) # optional - latte_int 36 - sage: len((2*simplex).integral_points()) # optional - latte_int + sage: len((2*simplex).integral_points()) # optional - latte_int 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),(-3,2,1),(1,-1,-2)], backend='normaliz') # optional - pynormaliz - sage: simplex = simplex.change_ring(QQ) # optional - pynormaliz - sage: poly = simplex.ehrhart_polynomial(engine = 'normaliz') # optional - pynormaliz - sage: poly # optional - pynormaliz + sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), # optional - pynormaliz + ....: (-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 7/2*t^3 + 2*t^2 - 1/2*t + 1 If the ``engine='normaliz'``, the backend should be ``'normaliz'``, otherwise it returns an error:: - sage: simplex = Polyhedron(vertices=[(0,0,0),(3,3,3),(-3,2,1),(1,-1,-2)]) + 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') # optional - pynormaliz Traceback (most recent call last): ... TypeError: The backend of the polyhedron should be 'normaliz' The polyhedron should be compact:: - sage: C = Polyhedron(backend='normaliz',rays=[[1,2],[2,1]]) # optional - pynormaliz - sage: C = C.change_ring(QQ) # optional - pynormaliz - sage: C.ehrhart_polynomial() # optional - pynormaliz + sage: C = Polyhedron(rays=[[1,2], [2,1]], # optional - pynormaliz + ....: backend='normaliz') + sage: C = C.change_ring(QQ) # optional - pynormaliz + sage: C.ehrhart_polynomial() # optional - pynormaliz Traceback (most recent call last): ... ValueError: Ehrhart polynomial only defined for compact polyhedra The polyhedron should have integral vertices:: - sage: L = Polyhedron(vertices = [[0],[1/2]]) + sage: L = Polyhedron(vertices=[[0], [1/2]]) sage: L.ehrhart_polynomial() Traceback (most recent call last): ... @@ -344,11 +348,11 @@ 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: P = polytopes.cube().change_ring(QQ) # optional - latte_int + sage: P.ehrhart_polynomial() # optional - latte_int 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)) # optional - latte_int + sage: Q.ehrhart_polynomial.is_in_cache() # optional - latte_int True """ # check if ``self`` is compact and has vertices in ZZ @@ -466,10 +470,11 @@ def ehrhart_quasipolynomial(self, variable='t', engine=None, verbose=False, the dilated line segment. Note that it is necessary to set the backend of the polytope to 'normaliz':: - sage: line_seg = Polyhedron(vertices=[[0],[1/2]],backend='normaliz') # optional - pynormaliz - sage: line_seg # optional - pynormaliz + sage: line_seg = Polyhedron(vertices=[[0], [1/2]], # optional - pynormaliz + ....: backend='normaliz') + sage: line_seg # optional - pynormaliz A 1-dimensional polyhedron in QQ^1 defined as the convex hull of 2 vertices - sage: line_seg.ehrhart_quasipolynomial() # optional - pynormaliz + sage: line_seg.ehrhart_quasipolynomial() # optional - pynormaliz (1/2*t + 1, 1/2*t + 1/2) For a more exciting example, let us look at the subpolytope of the @@ -477,34 +482,33 @@ def ehrhart_quasipolynomial(self, variable='t', engine=None, verbose=False, across the hyperplane `x_1 = x_4`:: sage: verts = [[3/2, 3, 4, 3/2], - ....: [3/2, 4, 3, 3/2], - ....: [5/2, 1, 4, 5/2], - ....: [5/2, 4, 1, 5/2], - ....: [7/2, 1, 2, 7/2], - ....: [7/2, 2, 1, 7/2]] - sage: subpoly = Polyhedron(vertices=verts, backend='normaliz') # optional - pynormaliz - sage: eq = subpoly.ehrhart_quasipolynomial() # optional - pynormaliz - sage: eq # optional - pynormaliz + ....: [3/2, 4, 3, 3/2], + ....: [5/2, 1, 4, 5/2], + ....: [5/2, 4, 1, 5/2], + ....: [7/2, 1, 2, 7/2], + ....: [7/2, 2, 1, 7/2]] + sage: subpoly = Polyhedron(vertices=verts, # optional - pynormaliz + ....: backend='normaliz') + sage: eq = subpoly.ehrhart_quasipolynomial(); eq # optional - pynormaliz (4*t^2 + 3*t + 1, 4*t^2 + 2*t) - sage: eq = subpoly.ehrhart_quasipolynomial() # optional - pynormaliz - sage: eq # optional - pynormaliz + sage: eq = subpoly.ehrhart_quasipolynomial(); eq # optional - pynormaliz (4*t^2 + 3*t + 1, 4*t^2 + 2*t) - sage: even_ep = eq[0] # optional - pynormaliz - sage: odd_ep = eq[1] # optional - pynormaliz - sage: even_ep(2) # optional - pynormaliz + sage: even_ep = eq[0] # optional - pynormaliz + sage: odd_ep = eq[1] # optional - pynormaliz + sage: even_ep(2) # optional - pynormaliz 23 - sage: ts = 2*subpoly # optional - pynormaliz - sage: ts.integral_points_count() # optional - pynormaliz latte_int + sage: ts = 2*subpoly # optional - pynormaliz + sage: ts.integral_points_count() # optional - pynormaliz latte_int 23 - sage: odd_ep(1) # optional - pynormaliz + sage: odd_ep(1) # optional - pynormaliz 6 - sage: subpoly.integral_points_count() # optional - pynormaliz latte_int + sage: subpoly.integral_points_count() # optional - pynormaliz latte_int 6 A polytope with rational nonintegral vertices must have ``backend='normaliz'``:: - sage: line_seg = Polyhedron(vertices=[[0],[1/2]]) + sage: line_seg = Polyhedron(vertices=[[0], [1/2]]) sage: line_seg.ehrhart_quasipolynomial() Traceback (most recent call last): ... @@ -512,8 +516,9 @@ def ehrhart_quasipolynomial(self, variable='t', engine=None, verbose=False, The polyhedron should be compact:: - sage: C = Polyhedron(backend='normaliz',rays=[[1/2,2],[2,1]]) # optional - pynormaliz - sage: C.ehrhart_quasipolynomial() # optional - pynormaliz + sage: C = Polyhedron(rays=[[1/2,2], [2,1]], # optional - pynormaliz + ....: backend='normaliz') + sage: C.ehrhart_quasipolynomial() # optional - pynormaliz Traceback (most recent call last): ... ValueError: Ehrhart quasipolynomial only defined for compact polyhedra @@ -521,12 +526,14 @@ 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),(-3,2,1),(1,-1,-2)], backend='normaliz') # optional - pynormaliz - sage: simplex = simplex.change_ring(QQ) # optional - pynormaliz - sage: poly = simplex.ehrhart_quasipolynomial(engine='normaliz') # optional - pynormaliz - sage: poly # optional - pynormaliz + sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), # optional - pynormaliz + ....: (-3,2,1),(1,-1,-2)], + ....: backend='normaliz') + sage: simplex = simplex.change_ring(QQ) # optional - pynormaliz + sage: poly = simplex.ehrhart_quasipolynomial( # optional - pynormaliz + ....: 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 - pynormaliz latte_int 7/2*t^3 + 2*t^2 - 1/2*t + 1 TESTS: @@ -596,31 +603,31 @@ def _ehrhart_quasipolynomial_normaliz(self, variable='t'): reflection across the hyperplane `x_1 = x_4`:: sage: verts = [[3/2, 3, 4, 3/2], - ....: [3/2, 4, 3, 3/2], - ....: [5/2, 1, 4, 5/2], - ....: [5/2, 4, 1, 5/2], - ....: [7/2, 1, 2, 7/2], - ....: [7/2, 2, 1, 7/2]] - sage: subpoly = Polyhedron(vertices=verts, backend='normaliz') # optional - pynormaliz - sage: eq = subpoly._ehrhart_quasipolynomial_normaliz() # optional - pynormaliz - sage: eq # optional - pynormaliz + ....: [3/2, 4, 3, 3/2], + ....: [5/2, 1, 4, 5/2], + ....: [5/2, 4, 1, 5/2], + ....: [7/2, 1, 2, 7/2], + ....: [7/2, 2, 1, 7/2]] + sage: subpoly = Polyhedron(vertices=verts, # optional - pynormaliz + ....: backend='normaliz') + sage: eq = subpoly._ehrhart_quasipolynomial_normaliz(); eq # optional - pynormaliz (4*t^2 + 3*t + 1, 4*t^2 + 2*t) - sage: even_ep = eq[0] # optional - pynormaliz - sage: odd_ep = eq[1] # optional - pynormaliz - sage: even_ep(2) # optional - pynormaliz + sage: even_ep = eq[0] # optional - pynormaliz + sage: odd_ep = eq[1] # optional - pynormaliz + sage: even_ep(2) # optional - pynormaliz 23 - sage: ts = 2*subpoly # optional - pynormaliz - sage: ts.integral_points_count() # optional - pynormaliz latte_int + sage: ts = 2*subpoly # optional - pynormaliz + sage: ts.integral_points_count() # optional - pynormaliz latte_int 23 - sage: odd_ep(1) # optional - pynormaliz + sage: odd_ep(1) # optional - pynormaliz 6 - sage: subpoly.integral_points_count() # optional - pynormaliz latte_int + sage: subpoly.integral_points_count() # optional - pynormaliz latte_int 6 TESTS:: sage: line_seg = Polyhedron(vertices=[[0],[1/2]]) - sage: line_seg._ehrhart_quasipolynomial_normaliz() # optional - pynormaliz + sage: line_seg._ehrhart_quasipolynomial_normaliz() # optional - pynormaliz Traceback (most recent call last): ... TypeError: The backend of the polyhedron should be 'normaliz' @@ -698,31 +705,30 @@ def _ehrhart_polynomial_latte(self, verbose=False, dual=None, EXAMPLES:: - sage: P = Polyhedron(vertices=[(0,0,0),(3,3,3),(-3,2,1),(1,-1,-2)]) - sage: p = P._ehrhart_polynomial_latte() # optional - latte_int - sage: p # optional - latte_int + sage: P = Polyhedron(vertices=[(0,0,0), (3,3,3), (-3,2,1), (1,-1,-2)]) + sage: p = P._ehrhart_polynomial_latte(); p # optional - latte_int 7/2*t^3 + 2*t^2 - 1/2*t + 1 - sage: p(1) # optional - latte_int + sage: p(1) # optional - latte_int 6 - sage: len(P.integral_points()) # optional - latte_int + sage: len(P.integral_points()) # optional - latte_int 6 - sage: p(2) # optional - latte_int + sage: p(2) # optional - latte_int 36 - sage: len((2*P).integral_points()) # optional - latte_int + sage: len((2*P).integral_points()) # optional - latte_int 36 The unit hypercubes:: 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 + ....: return Polyhedron(vertices=list(product([0,1], repeat=d))) + sage: hypercube(3)._ehrhart_polynomial_latte() # optional - latte_int t^3 + 3*t^2 + 3*t + 1 - sage: hypercube(4)._ehrhart_polynomial_latte() # optional - latte_int + sage: hypercube(4)._ehrhart_polynomial_latte() # optional - latte_int 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() # optional - latte_int 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() # optional - latte_int t^6 + 6*t^5 + 15*t^4 + 20*t^3 + 15*t^2 + 6*t + 1 TESTS: @@ -822,50 +828,55 @@ def fixed_subpolytope(self, vertex_permutation): The fixed subpolytopes of the cube can be obtained as follows:: - sage: Cube = polytopes.cube(backend = 'normaliz') # optional - pynormaliz - sage: AG = Cube.restricted_automorphism_group(output='permutation') # optional - pynormaliz - sage: reprs = AG.conjugacy_classes_representatives() # optional - pynormaliz + sage: Cube = polytopes.cube(backend = 'normaliz') # optional - pynormaliz + sage: AG = Cube.restricted_automorphism_group( # optional - pynormaliz + ....: output='permutation') + sage: reprs = AG.conjugacy_classes_representatives() # optional - pynormaliz The fixed subpolytope of the identity element of the group is the entire cube:: - sage: reprs[0] # optional - pynormaliz + sage: reprs[0] # optional - pynormaliz () - sage: Cube.fixed_subpolytope(vertex_permutation = reprs[0]) # optional - pynormaliz + sage: Cube.fixed_subpolytope(vertex_permutation=reprs[0]) # optional - pynormaliz A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 8 vertices - sage: _.vertices() # optional - pynormaliz + sage: _.vertices() # optional - pynormaliz (A vertex at (-1, -1, -1), - A vertex at (-1, -1, 1), - A vertex at (-1, 1, -1), - A vertex at (-1, 1, 1), - A vertex at (1, -1, -1), - A vertex at (1, -1, 1), - A vertex at (1, 1, -1), - A vertex at (1, 1, 1)) + A vertex at (-1, -1, 1), + A vertex at (-1, 1, -1), + A vertex at (-1, 1, 1), + A vertex at (1, -1, -1), + A vertex at (1, -1, 1), + A vertex at (1, 1, -1), + A vertex at (1, 1, 1)) You can obtain non-trivial examples:: - sage: fsp = Cube.fixed_subpolytope(AG([(0,1),(2,3),(4,5),(6,7)]));fsp # optional - pynormaliz + sage: G = AG([(0,1),(2,3),(4,5),(6,7)]) + sage: fsp = Cube.fixed_subpolytope(G); fsp # optional - pynormaliz A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices - sage: fsp.vertices() # optional - pynormaliz + sage: fsp.vertices() # optional - pynormaliz (A vertex at (-1, -1, 0), - A vertex at (-1, 1, 0), - A vertex at (1, -1, 0), - A vertex at (1, 1, 0)) + A vertex at (-1, 1, 0), + A vertex at (1, -1, 0), + A vertex at (1, 1, 0)) - The next example shows that fixed_subpolytope works for rational polytopes:: + The next example shows that :meth:`fixed_subpolytope` works for rational polytopes:: - sage: P = Polyhedron(vertices=[[0],[1/2]], backend='normaliz') # optional - pynormaliz - sage: P.vertices() # optional - pynormaliz + sage: P = Polyhedron(vertices=[[0], [1/2]], # optional - pynormaliz + ....: backend='normaliz') + sage: P.vertices() # optional - pynormaliz (A vertex at (0), A vertex at (1/2)) - sage: G = P.restricted_automorphism_group(output='permutation');G # optional - pynormaliz + sage: G = P.restricted_automorphism_group( # optional - pynormaliz + ....: output='permutation'); G Permutation Group with generators [(0,1)] - sage: len(G) # optional - pynormaliz + sage: len(G) # optional - pynormaliz 2 - sage: fixed_set = P.fixed_subpolytope(G.gens()[0]); fixed_set # optional - pynormaliz + sage: fixed_set = P.fixed_subpolytope(G.gens()[0]) # optional - pynormaliz + 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() # optional - pynormaliz [[1/4]] """ if self.is_empty(): @@ -929,22 +940,23 @@ 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: p = polytopes.hypercube(2, backend='normaliz'); p # optional - pynormaliz A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices - sage: aut_p = p.restricted_automorphism_group(output='permutation') # optional - pynormaliz # optional - sage.groups - sage: aut_p.order() # optional - pynormaliz # optional - sage.groups + sage: aut_p = p.restricted_automorphism_group( # optional - pynormaliz sage.groups + ....: output='permutation') + sage: aut_p.order() # optional - pynormaliz sage.groups 8 - sage: conj_list = aut_p.conjugacy_classes_representatives(); # optional - pynormaliz # optional - sage.groups - sage: fixedpolytopes_dictionary = p.fixed_subpolytopes(conj_list) # optional - pynormaliz # optional - sage.groups - sage: fixedpolytopes_dictionary[aut_p([(0,3),(1,2)])] # optional - pynormaliz # optional - sage.groups + 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 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') # optional - sage.groups + sage: conj_list = aut_P.conjugacy_classes_representatives() # optional - sage.groups + sage: P.fixed_subpolytopes(conj_list) # optional - sage.groups Traceback (most recent call last): ... NotImplementedError: unbounded polyhedra are not supported @@ -1010,14 +1022,15 @@ 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: S = polytopes.simplex(3, backend='normaliz'); S # optional - pynormaliz A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 4 vertices - sage: G = S.restricted_automorphism_group(output = 'permutation') # optional - pynormaliz - sage: G.is_isomorphic(SymmetricGroup(4)) # optional - pynormaliz + sage: G = S.restricted_automorphism_group( # optional - pynormaliz + ....: output='permutation') + sage: G.is_isomorphic(SymmetricGroup(4)) # optional - pynormaliz True - sage: Hstar = S._Hstar_function_normaliz(G); Hstar # optional - pynormaliz + sage: Hstar = S._Hstar_function_normaliz(G); Hstar # optional - pynormaliz chi_4 - sage: G.character_table() # optional - pynormaliz + sage: G.character_table() # optional - pynormaliz [ 1 -1 1 1 -1] [ 3 -1 0 -1 1] [ 2 0 -1 2 0] @@ -1029,37 +1042,44 @@ 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],[-1,0,-1],[0,1,1], # optional - pynormaliz - ....: [0,-1,-1],[1,1,1],[-1,-1,-1]], + sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], # optional - pynormaliz + ....: [-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 - pynormaliz - 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, acting_group = G) # optional - pynormaliz - sage: list(Dict.keys())[0] # optional - pynormaliz + sage: K = P.restricted_automorphism_group( # optional - pynormaliz + ....: 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 + ....: acting_group=G) + sage: list(Dict.keys())[0] # optional - pynormaliz (0,2)(1,3)(4,6)(5,7) - sage: list(Dict.values())[0] # optional - pynormaliz + sage: list(Dict.values())[0] # optional - pynormaliz [-1 0 1 0] [ 0 1 0 0] [ 0 0 1 0] [ 0 0 0 1] - sage: len(G) # optional - pynormaliz + sage: len(G) # optional - pynormaliz 2 - sage: G.character_table() # optional - pynormaliz + sage: G.character_table() # optional - pynormaliz [ 1 1] [ 1 -1] Then we calculate the rational function `H^*(t)`:: - sage: Hst = P._Hstar_function_normaliz(G); Hst # optional - pynormaliz - (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: Hst = P._Hstar_function_normaliz(G); Hst # optional - pynormaliz + (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) To see the exact as written in [Stap2011]_, we can format it as ``'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 - pynormaliz - ((t^4 + 3*t^3 + 8*t^2 + 3*t + 1)/(t + 1), (3*t^3 + 2*t^2 + 3*t)/(t + 1)) + sage: lin = P._Hstar_function_normaliz(G, # optional - pynormaliz + ....: output='Hstar_as_lin_comb') + sage: lin + ((t^4 + 3*t^3 + 8*t^2 + 3*t + 1)/(t + 1), + (3*t^3 + 2*t^2 + 3*t)/(t + 1)) """ if self.is_empty(): raise NotImplementedError('empty polyhedra are not supported') @@ -1079,26 +1099,26 @@ def _Hstar_function_normaliz(self, acting_group=None, output=None): INPUT: - ``acting_group`` -- (default=None) a permgroup object. A subgroup of - `self`'s ``restricted_automorphism_group`` output as a permutation. + ``self``'s ``restricted_automorphism_group`` output as a permutation. If ``None``, it is set to the full ``restricted_automorphism_group`` - of `self`. The acting group should always use output='permutation'. + of ``self``. The acting group should always use ``output='permutation'``. - ``output`` -- string. an output option. The allowed values are: - * ``None`` (default): returns the rational function `H^*(t)`. `H^*` - is a rational function in `t` with coefficients in the ring of - class functions. - * ``'e_series_list'``: Returns a list of the ehrhart_series - for the fixed_subpolytopes of each conjugacy class representative. - * ``'determinant_vec'``: Returns a list of the determinants - of `Id-\rho*t` for each conjugacy class representative. - * ``'Hstar_as_lin_comb'``: Returns a vector of the coefficients - of the irreducible representations in the expression of `H^*`. - * ``'prod_det_es'``: Returns a vector of the product of - determinants and the Ehrhart series. - * ``'complete'``: Returns a list with Hstar, - Hstar_as_lin_comb, character table of the acting group, and - whether Hstar is effective. + * ``None`` (default): Returns the rational function `H^*(t)`. `H^*` + is a rational function in `t` with coefficients in the ring of + class functions. + * ``'e_series_list'``: Returns a list of the ehrhart_series + for the fixed_subpolytopes of each conjugacy class representative. + * ``'determinant_vec'``: Returns a list of the determinants + of `Id-\rho*t` for each conjugacy class representative. + * ``'Hstar_as_lin_comb'``: Returns a vector of the coefficients + of the irreducible representations in the expression of `H^*`. + * ``'prod_det_es'``: Returns a vector of the product of + determinants and the Ehrhart series. + * ``'complete'``: Returns a list with ``Hstar``, + ``Hstar_as_lin_comb``, character table of the acting group, and + whether ``Hstar`` is effective. OUTPUT: @@ -1152,28 +1172,35 @@ 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(output='permutation') # optional - pynormaliz - 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: p3 = polytopes.permutahedron(3, backend='normaliz') # optional - pynormaliz + sage: G = p3.restricted_automorphism_group( # optional - pynormaliz + ....: 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 True - sage: [Hstar, Hlin] = [p3.Hstar_function(S3), p3.Hstar_function(S3, output = 'Hstar_as_lin_comb')] # optional - pynormaliz - sage: p3.is_effective(Hstar,Hlin) # optional - pynormaliz + sage: Hstar = p3.Hstar_function(S3) # optional - pynormaliz + sage: Hlin = p3.Hstar_function(S3, # optional - pynormaliz + ....: output='Hstar_as_lin_comb')] + sage: p3.is_effective(Hstar,Hlin) # optional - pynormaliz 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],[-1,0,-1],[0,1,1], # optional - pynormaliz - ....: [0,-1,-1],[1,1,1],[-1,-1,-1]], + sage: P = Polyhedron(vertices=[[0,0,1], [0,0,-1], [1,0,1], # optional - pynormaliz + ....: [-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 - pynormaliz - 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 - (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 - pynormaliz - sage: P.is_effective(Hstar, Hstar_lin) # optional - pynormaliz + sage: G = P.restricted_automorphism_group( # optional - pynormaliz + ....: 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 + (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 + ....: output='Hstar_as_lin_comb') + sage: P.is_effective(Hstar, Hstar_lin) # optional - pynormaliz False """ if self.is_empty(): @@ -1213,10 +1240,12 @@ class functions of the acting group. A character `\rho` is effective if TESTS:: - sage: p1 = Polyhedron(vertices = [[0],[1/2]]); - sage: p2 = Polyhedron(vertices = [[0],[1/2]], backend='normaliz') # optional - pynormaliz - sage: [Hstar,Hstarlin] = [p2.Hstar_function(),p2.Hstar_function(output='Hstar_as_lin_comb')] # optional - pynormaliz - sage: p1._is_effective_normaliz(Hstar,Hstarlin) # optional - pynormaliz + sage: p1 = Polyhedron(vertices=[[0], [1/2]]) + sage: p2 = Polyhedron(vertices=[[0], [1/2]], # optional - pynormaliz + ....: backend='normaliz') + sage: Hstar = p2.Hstar_function() + sage: Hstarlin = p2.Hstar_function(output='Hstar_as_lin_comb')] # optional - pynormaliz + sage: p1._is_effective_normaliz(Hstar, Hstarlin) # optional - pynormaliz Traceback (most recent call last): ... TypeError: the backend of the polyhedron should be 'normaliz' diff --git a/src/sage/geometry/polyhedron/base_RDF.py b/src/sage/geometry/polyhedron/base_RDF.py index b97323c280f..fe75503edf2 100644 --- a/src/sage/geometry/polyhedron/base_RDF.py +++ b/src/sage/geometry/polyhedron/base_RDF.py @@ -1,3 +1,5 @@ +# sage.doctest: optional - sage.rings.real_double + """ Base class for polyhedra over ``RDF`` """ diff --git a/src/sage/geometry/polyhedron/base_number_field.py b/src/sage/geometry/polyhedron/base_number_field.py index c802207303f..40b9017dc53 100644 --- a/src/sage/geometry/polyhedron/base_number_field.py +++ b/src/sage/geometry/polyhedron/base_number_field.py @@ -32,9 +32,9 @@ 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 # optional - sage.rings.number_field 1.414213562373095? - sage: rt3 = AA(sqrt(3)); rt3 # optional - sage.rings.number_field + sage: rt3 = AA(sqrt(3)); rt3 # optional - sage.rings.number_field 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 @@ -58,39 +58,41 @@ 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: p = Polyhedron(vertices=[(0,1/2), (2,0), (4,5/6)], # optional - pynormaliz ....: base_ring=AA, backend='normaliz') - sage: def convert_QQ(ieqs, eqs): # optional - pynormaliz - ....: 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_QQ(ieqs, eqs): # optional - pynormaliz + ....: 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 ....: return ieqs, eqs - sage: p._compute_data_lists_and_internal_base_ring([[[1]], [[1/2]]], # optional - pynormaliz - ....: convert_QQ, convert_NF) + sage: p._compute_data_lists_and_internal_base_ring( # optional - pynormaliz + ....: [[[1]], [[1/2]]], convert_QQ, convert_NF) (([[1000]], [[500]]), Rational Field) - sage: p._compute_data_lists_and_internal_base_ring([[[AA(1)]], [[1/2]]], # optional - pynormaliz - ....: convert_QQ, convert_NF) + sage: p._compute_data_lists_and_internal_base_ring( # optional - pynormaliz + ....: [[[AA(1)]], [[1/2]]], convert_QQ, convert_NF) (([[1000]], [[500]]), Rational Field) - sage: p._compute_data_lists_and_internal_base_ring([[[AA(sqrt(2))]], [[1/2]]], # optional - pynormaliz # optional - sage.rings.number_field - ....: convert_QQ, convert_NF) + sage: p._compute_data_lists_and_internal_base_ring( # optional - pynormaliz sage.rings.number_field + ....: [[[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(vertices=[(a,1/2),(2,0),(4,5/6)], # indirect doctest # optional - pynormaliz # optional - sage.rings.number_field - ....: base_ring=K, backend='normaliz') + sage: K. = QuadraticField(-5) # optional - sage.rings.number_field + sage: p = Polyhedron(base_ring=K, # indirect doctest # optional - pynormaliz sage.rings.number_field + ....: backend='normaliz', + ....: vertices=[(a,1/2), (2,0), (4,5/6)]) Traceback (most recent call last): ... ValueError: invalid base ring: Number Field in a ... is not real embedded Checks that :trac:`30248` is fixed:: - sage: q = Polyhedron(backend='normaliz', base_ring=AA, # indirect doctest # optional - pynormaliz # optional - sage.rings.number_field + sage: q = Polyhedron(base_ring=AA, # indirect doctest # optional - pynormaliz 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 # optional - sage.rings.number_field + sage: -q # optional - pynormaliz 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 a415bc44671..96861800a40 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() # optional - sage.graphs Graph on 16 vertices - sage: C.facet_graph() # optional - sage.graphs + sage: C.facet_graph() # optional - sage.graphs Graph on 8 vertices Face lattice:: - sage: C.face_lattice() # optional - sage.combinat + sage: C.face_lattice() # optional - sage.combinat Finite lattice containing 82 elements Face iterator:: @@ -329,7 +329,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() # optional - sage.combinat Traceback (most recent call last): ... ValueError: the combinatorial polyhedron was not initialized @@ -613,16 +613,16 @@ 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: 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 ....: face.ambient_Hrepresentation()) for face in it) - sage: tup1 = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + sage: tup1 = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat ....: face.ambient_Hrepresentation()) for face in it1) - sage: tup == tup1 # optional - sage.combinat + sage: tup == tup1 # optional - sage.combinat True sage: P = polytopes.cyclic_polytope(4,10) @@ -720,9 +720,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) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.Hrepresentation() # optional - sage.combinat (An inequality (1, 1, 0) x - 3 >= 0, An inequality (-1, -1, 0) x + 5 >= 0, An inequality (0, 1, 0) x - 1 >= 0, @@ -1077,10 +1077,10 @@ 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: 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 True The incidence matrix is consistent with @@ -1257,15 +1257,14 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.cyclic_polytope(3,5) sage: C = CombinatorialPolyhedron(P) - sage: C.vertex_graph() + sage: G = C.vertex_graph(); G # optional - sage.graphs Graph on 5 vertices - sage: G = C.vertex_graph() - sage: sorted(G.degree()) + sage: sorted(G.degree()) # optional - sage.graphs [3, 3, 4, 4, 4] sage: P = Polyhedron(rays=[[1]]) sage: C = CombinatorialPolyhedron(P) - sage: C.graph() + sage: C.graph() # optional - sage.graphs Graph on 1 vertex """ vertices = self.vertices(names=names) @@ -1366,11 +1365,11 @@ 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: P = polytopes.permutahedron(2) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.ridges() # optional - sage.combinat ((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) # optional - sage.combinat (((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)),) @@ -1539,25 +1538,25 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.cyclic_polytope(4,6) sage: C = CombinatorialPolyhedron(P) - sage: C.facet_graph() + sage: C.facet_graph() # optional - sage.graphs Graph on 9 vertices TESTS:: sage: P = Polyhedron(ieqs=[[1,-1,0],[1,1,0]]) - sage: CombinatorialPolyhedron(P).facet_graph() + sage: CombinatorialPolyhedron(P).facet_graph() # optional - 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) + sage: C.facet_graph(names=False) # optional - sage.graphs Graph on 6 vertices - sage: C = CombinatorialPolyhedron(polytopes.hypersimplex(5,2)); C + sage: C = CombinatorialPolyhedron(polytopes.hypersimplex(5,2)); C # optional - sage.combinat A 4-dimensional combinatorial polyhedron with 10 facets - sage: C.facet_graph() + sage: C.facet_graph() # optional - sage.graphs sage.combinat Graph on 10 vertices """ face_iter = self.face_iter(self.dimension() - 1, algorithm='primal') @@ -1595,7 +1594,7 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.hypercube(2).pyramid() sage: C = CombinatorialPolyhedron(P) - sage: G = C.vertex_facet_graph(); G + sage: G = C.vertex_facet_graph(); G # optional - sage.graphs Digraph on 10 vertices sage: C.Vrepresentation() (A vertex at (0, -1, -1), @@ -1603,7 +1602,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])) + sage: sorted(G.neighbors_out(C.Vrepresentation()[4])) # optional - 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, @@ -1616,7 +1615,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) + sage: C.vertex_facet_graph().vertices(sort=True) # optional - sage.graphs [('H', 0), ('H', 1), ('H', 2), @@ -1630,18 +1629,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) + sage: C.vertex_facet_graph(names=False).vertices(sort=True) # optional - sage.graphs [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] TESTS: Test that :trac:`29898` is fixed:: - sage: Polyhedron().vertex_facet_graph() + sage: Polyhedron().vertex_facet_graph() # optional - sage.graphs Digraph on 0 vertices - sage: Polyhedron([[0]]).vertex_facet_graph() + sage: Polyhedron([[0]]).vertex_facet_graph() # optional - sage.graphs Digraph on 1 vertex - sage: Polyhedron([[0]]).vertex_facet_graph(False) + sage: Polyhedron([[0]]).vertex_facet_graph(False) # optional - sage.graphs Digraph on 1 vertex """ from sage.graphs.digraph import DiGraph @@ -1710,9 +1709,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) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.f_vector() # optional - sage.combinat (1, 120, 240, 150, 30, 1) sage: P = polytopes.cyclic_polytope(6,10) @@ -1722,9 +1721,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) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.f_vector(num_threads=2) # optional - sage.combinat (1, 120, 240, 150, 30, 1) TESTS:: @@ -1782,7 +1781,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() # optional - sage.combinat {(-1,): 1, (0,): 16, (0, 1): 64, @@ -1803,38 +1802,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) # optional - sage.combinat 64 - sage: C.flag_f_vector(2) # optional - sage.combinat + sage: C.flag_f_vector(2) # optional - 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) # optional - sage.combinat 64 - sage: C.flag_f_vector(-1,0,3,4) # optional - sage.combinat + sage: C.flag_f_vector(-1,0,3,4) # optional - 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) # optional - sage.combinat 1 - sage: C.flag_f_vector(4) # optional - sage.combinat + sage: C.flag_f_vector(4) # optional - 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() # optional - 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) # optional - 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) # optional - sage.combinat Traceback (most recent call last): ... KeyError: (3, 0) @@ -1862,7 +1861,7 @@ cdef class CombinatorialPolyhedron(SageObject): TESTS:: sage: C = CombinatorialPolyhedron(3) - sage: C._flag_f_vector() # optional - sage.combinat + sage: C._flag_f_vector() # optional - 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() @@ -2060,8 +2059,8 @@ cdef class CombinatorialPolyhedron(SageObject): sage: CombinatorialPolyhedron(cyclic).simpliciality() 3 - sage: hypersimplex = polytopes.hypersimplex(5,2) - sage: CombinatorialPolyhedron(hypersimplex).simpliciality() + sage: hypersimplex = polytopes.hypersimplex(5,2) # optional - sage.combinat + sage: CombinatorialPolyhedron(hypersimplex).simpliciality() # optional - sage.combinat 2 sage: cross = polytopes.cross_polytope(4) @@ -2168,16 +2167,16 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: hyper4 = polytopes.hypersimplex(4,2) - sage: CombinatorialPolyhedron(hyper4).simplicity() + sage: hyper4 = polytopes.hypersimplex(4,2) # optional - sage.combinat + sage: CombinatorialPolyhedron(hyper4).simplicity() # optional - sage.combinat 1 - sage: hyper5 = polytopes.hypersimplex(5,2) - sage: CombinatorialPolyhedron(hyper5).simplicity() + sage: hyper5 = polytopes.hypersimplex(5,2) # optional - sage.combinat + sage: CombinatorialPolyhedron(hyper5).simplicity() # optional - sage.combinat 2 - sage: hyper6 = polytopes.hypersimplex(6,2) - sage: CombinatorialPolyhedron(hyper6).simplicity() + sage: hyper6 = polytopes.hypersimplex(6,2) # optional - sage.combinat + sage: CombinatorialPolyhedron(hyper6).simplicity() # optional - sage.combinat 3 sage: P = polytopes.simplex(3) @@ -2605,15 +2604,15 @@ 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: P = polytopes.permutahedron(4) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.join_of_Vrep(0,1) # optional - sage.combinat 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() # optional - sage.combinat (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() # optional - sage.combinat (8,) - sage: C.join_of_Vrep().ambient_V_indices() # optional - sage.combinat + sage: C.join_of_Vrep().ambient_V_indices() # optional - sage.combinat () """ return self.face_generator().join_of_Vrep(*indices) @@ -2628,19 +2627,19 @@ 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: 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 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() # optional - sage.rings.number_field (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() # optional - sage.rings.number_field (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() # optional - sage.rings.number_field (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() # optional - sage.rings.number_field (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() # optional - sage.rings.number_field () """ return self.face_generator().meet_of_Hrep(*indices) @@ -2671,38 +2670,38 @@ 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: 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 A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_Vrepresentation() # optional - sage.combinat + sage: face.ambient_Vrepresentation() # optional - sage.combinat (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 # optional - sage.combinat A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_Vrepresentation() # optional - sage.combinat + sage: face.ambient_Vrepresentation() # optional - sage.combinat (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() # optional - sage.combinat (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() # optional - sage.combinat (25, 29, 30) - sage: face = next(it); face # optional - sage.combinat + sage: face = next(it); face # optional - sage.combinat A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_H_indices() # optional - sage.combinat + sage: face.ambient_H_indices() # optional - sage.combinat (24, 29, 30) - sage: face.ambient_V_indices() # optional - sage.combinat + sage: face.ambient_V_indices() # optional - sage.combinat (32, 89, 90, 94) sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3],[0,2,3],[1,2,3]]) @@ -2814,31 +2813,31 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = Polyhedron(rays=[[1,0],[0,1]]) sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice() + sage: C.face_lattice() # optional - 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()) + sage: C.face_lattice().is_isomorphic(C1.face_lattice()) # optional - 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) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.face_lattice() # optional - 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()) + sage: C.face_lattice().is_isomorphic(P.face_lattice()) # optional - 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) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.face_lattice().is_isomorphic(P.face_lattice()) # optional - sage.combinat True """ from sage.combinat.posets.lattices import FiniteLatticePoset @@ -2870,18 +2869,18 @@ cdef class CombinatorialPolyhedron(SageObject): 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 # optional - sage.rings.number_field + sage: D = C.hasse_diagram(); D # optional - sage.graphs sage.rings.number_field Digraph on 20 vertices - sage: D.average_degree() # optional - sage.graphs # optional - sage.rings.number_field + sage: D.average_degree() # optional - sage.graphs sage.rings.number_field 21/5 - sage: D.relabel(C.face_by_face_lattice_index) # optional - sage.graphs # optional - sage.rings.number_field - sage: dim_0_vert = D.vertices(sort=True)[1:6]; dim_0_vert # optional - sage.graphs # optional - sage.rings.number_field + 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 [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 # optional - sage.rings.number_field + sage: sorted(D.out_degree(vertices=dim_0_vert)) # optional - sage.graphs sage.rings.number_field [3, 3, 3, 3, 4] """ if not self._face_lattice_incidences: @@ -2910,12 +2909,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() # optional - 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) # optional - sage.combinat + sage: set(G._elements) # optional - sage.combinat {(0, -1), (1, 0), (2, 0), @@ -2966,13 +2965,13 @@ cdef class CombinatorialPolyhedron(SageObject): 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() # optional - sage.combinat + sage: F # optional - sage.combinat 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) # optional - sage.combinat + sage: G.level_sets()[0] # optional - sage.combinat [A -1-dimensional face of a 3-dimensional combinatorial polyhedron] - sage: G.level_sets()[3] # optional - sage.combinat + sage: G.level_sets()[3] # optional - sage.combinat [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, @@ -2982,9 +2981,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() # optional - sage.combinat + sage: G = F.relabel(C.face_by_face_lattice_index) # optional - sage.combinat + sage: G._elements # optional - 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, @@ -2992,8 +2991,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) # optional - sage.combinat + sage: G._elements # optional - sage.combinat ((), (0,), (0, 1), (0, 2), (0, 1, 2)) """ self._record_all_faces() # Initialize ``_all_faces``, if not done yet. @@ -3038,13 +3037,13 @@ 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: 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 [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] # optional - sage.combinat [(16,), (15, 16), (8, 9, 14, 15, 16, 17)] sage: P = Polyhedron(rays=[[1,0]], lines=[[0,1]]) @@ -3340,7 +3339,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()) # optional - sage.combinat True Polar is an alias to be consistent with :class:`~sage.geometry.polyhedron.base.Polyhedron_base`:: @@ -3390,7 +3389,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()) # optional - sage.combinat True One can specify a name for the new vertex:: @@ -3409,10 +3408,10 @@ 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: 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 (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, @@ -3761,15 +3760,17 @@ 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: 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 ....: face.ambient_Hrepresentation()) for face in it) - sage: rg = range(1,sum(C.f_vector()) - 1) # optional - sage.combinat - sage: tup2 = tuple((C.face_by_face_lattice_index(i).ambient_Vrepresentation(), # optional - sage.combinat - ....: C.face_by_face_lattice_index(i).ambient_Hrepresentation()) for i in rg) - sage: sorted(tup) == sorted(tup2) # optional - sage.combinat + sage: rg = range(1,sum(C.f_vector()) - 1) # optional - sage.combinat + sage: tup2 = tuple( # optional - sage.combinat + ....: (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 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 b1f529c412d..e499afcbc1c 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx @@ -100,7 +100,7 @@ cdef class CombinatorialFace(SageObject): sage: F = C.face_lattice() # optional - sage.combinat sage: F._elements[3] # optional - sage.combinat 34 - sage: C.face_by_face_lattice_index(29) + sage: C.face_by_face_lattice_index(29) # optional - sage.combinat A 1-dimensional face of a 5-dimensional combinatorial polyhedron Obtain the dimension of a combinatorial face:: 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 a1c4152bf42..5b822e51f6b 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,8 @@ cdef class PolyhedronFaceLattice: sage: P = polytopes.Birkhoff_polytope(3) sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice() # indirect doctests + sage: C._record_all_faces() # indirect doctests + sage: C.face_lattice() # optional - sage.combinat Finite lattice containing 50 elements ALGORITHM: @@ -215,7 +216,7 @@ cdef class PolyhedronFaceLattice: sage: P = polytopes.cube() sage: C = CombinatorialPolyhedron(P) sage: C._record_all_faces() # indirect doctests - sage: C.face_lattice() + sage: C.face_lattice() # optional - 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 0a8cc1854ac..4e291e689dd 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 # optional - sage.symbolic - sage: triangle.Hrepresentation() # optional - sage.rings.number_field # optional - sage.symbolic + 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 (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,21 +186,23 @@ 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)]) # optional - 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() # optional - sage.symbolic False Even faster than all algebraic real numbers (the field ``AA``) is to take the smallest extension field. For the equilateral triangle, that would be:: - 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 - 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 + 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 + 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 .. WARNING:: @@ -217,7 +219,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]]) # optional - sage.rings.real_mpfr Traceback (most recent call last): ... ValueError: the only allowed inexact ring is 'RDF' with backend 'cdd' @@ -449,25 +451,25 @@ 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 # optional - sage.rings.number_field - sage: icosah = Polyhedron( # optional - sage.combinat # optional - sage.rings.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 ....: [(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 # optional - sage.rings.number_field + sage: len(icosah.faces(2)) # optional - sage.combinat sage.rings.number_field 20 When the input contains elements of a Number Field, they require an embedding:: - 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') # 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 Traceback (most recent call last): ... ValueError: invalid base ring @@ -504,12 +506,12 @@ 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: H. = HyperplaneArrangements(QQ) # optional - sage.combinat + sage: h = x + y - 1; h # optional - sage.combinat Hyperplane x + y - 1 - sage: Polyhedron(h, base_ring=ZZ) # optional - sage.combinat + sage: Polyhedron(h, base_ring=ZZ) # optional - sage.combinat 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) # optional - sage.combinat A 1-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line .. NOTE:: @@ -563,7 +565,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), # optional - sage.rings.real_mpfr ....: (6.4876921900819049, 4.8435898415984129)]) Traceback (most recent call last): ... @@ -571,11 +573,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)) # optional - 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)) # optional - 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/face.py b/src/sage/geometry/polyhedron/face.py index 2166f016ba8..437e296ceb9 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() # optional - 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(): # optional - 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(): # optional - sage.combinat ....: print(fl.ambient_Vrepresentation()) () (A vertex at (1, -1),) @@ -478,15 +478,14 @@ def n_ambient_Hrepresentation(self): EXAMPLES:: sage: p = polytopes.cross_polytope(4) - sage: face = p.face_lattice()[5] # optional - sage.combinat - sage: face # optional - sage.combinat + sage: face = p.face_lattice()[5]; face # optional - 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() # optional - 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() # optional - sage.combinat 4 """ return len(self.ambient_Hrepresentation()) @@ -505,12 +504,11 @@ def n_ambient_Vrepresentation(self): EXAMPLES:: sage: p = polytopes.cross_polytope(4) - sage: face = p.face_lattice()[5] # optional - sage.combinat - sage: face # optional - sage.combinat + sage: face = p.face_lattice()[5]; face # optional - 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() # optional - 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() # optional - sage.combinat 2 """ return len(self.ambient_Vrepresentation()) @@ -595,8 +593,8 @@ def dim(self): EXAMPLES:: - sage: fl = polytopes.dodecahedron().face_lattice() # optional - sage.combinat # optional - sage.rings.number_field - sage: sorted([ x.dim() for x in fl ]) # optional - sage.combinat # optional - sage.rings.number_field + 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 [-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] @@ -605,7 +603,7 @@ def dim(self): Check that :trac:`28650` is fixed:: - sage: P = Polyhedron(vertices=[[1,0]], rays=[[1,0],[0,1]]) + sage: P = Polyhedron(vertices=[[1,0]], rays=[[1,0], [0,1]]) sage: P.faces(2) (A 2-dimensional face of a Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 2 rays,) """ @@ -679,8 +677,7 @@ def polyhedron(self): sage: P = polytopes.cross_polytope(3); P A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices - sage: face = P.facets()[3] - sage: face + sage: face = P.facets()[3]; face A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices sage: face.polyhedron() A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices @@ -704,10 +701,11 @@ def ambient_vector_space(self, base_field=None): sage: half_plane = Polyhedron(ieqs=[(0,1,0)]) sage: line = half_plane.faces(1)[0]; line - A 1-dimensional face of a Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line + A 1-dimensional face of a + 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) # optional - sage.rings.number_field Vector space of dimension 2 over Algebraic Real Field """ return self.polyhedron().ambient_vector_space(base_field=base_field) @@ -716,15 +714,14 @@ def is_relatively_open(self): r""" Return whether ``self`` is relatively open. - OUTPUT: - - Boolean. + OUTPUT: Boolean. EXAMPLES:: sage: half_plane = Polyhedron(ieqs=[(0,1,0)]) sage: line = half_plane.faces(1)[0]; line - A 1-dimensional face of a Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line + A 1-dimensional face of a + Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line sage: line.is_relatively_open() True """ @@ -734,15 +731,14 @@ def is_compact(self): r""" Return whether ``self`` is compact. - OUTPUT: - - Boolean. + OUTPUT: Boolean. EXAMPLES:: sage: half_plane = Polyhedron(ieqs=[(0,1,0)]) sage: line = half_plane.faces(1)[0]; line - A 1-dimensional face of a Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line + A 1-dimensional face of a + Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line sage: line.is_compact() False """ @@ -762,9 +758,9 @@ def as_polyhedron(self, **kwds): sage: P = polytopes.cross_polytope(3); P A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices - sage: face = P.faces(2)[3] - sage: face - A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices + sage: face = P.faces(2)[3]; face + A 2-dimensional face of a + Polyhedron in ZZ^3 defined as the convex hull of 3 vertices sage: face.as_polyhedron() A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 3 vertices @@ -791,9 +787,9 @@ def _some_elements_(self): sage: P = polytopes.cross_polytope(3); P A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 6 vertices - sage: face = P.faces(2)[3] - sage: face - A 2-dimensional face of a Polyhedron in ZZ^3 defined as the convex hull of 3 vertices + sage: face = P.faces(2)[3]; face + A 2-dimensional face of a + Polyhedron in ZZ^3 defined as the convex hull of 3 vertices sage: face.as_polyhedron().vertices() (A vertex at (0, -1, 0), A vertex at (0, 0, -1), A vertex at (1, 0, 0)) sage: face.an_element() # indirect doctest @@ -815,7 +811,8 @@ def contains(self, point): sage: half_plane = Polyhedron(ieqs=[(0,1,0)]) sage: line = half_plane.faces(1)[0]; line - A 1-dimensional face of a Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line + A 1-dimensional face of a + Polyhedron in QQ^2 defined as the convex hull of 1 vertex and 1 line sage: line.contains([0, 1]) True @@ -864,7 +861,7 @@ def normal_cone(self, direction='outer'): EXAMPLES:: - sage: p = Polyhedron(vertices = [[1,2],[2,1],[-2,2],[-2,-2],[2,-2]]) + sage: p = Polyhedron(vertices=[[1,2], [2,1], [-2,2], [-2,-2], [2,-2]]) sage: for v in p.face_generator(0): ....: vect = v.vertices()[0].vector() ....: nc = v.normal_cone().rays_list() @@ -894,11 +891,14 @@ def normal_cone(self, direction='outer'): sage: f2 = p.faces(1)[0] sage: f3 = p.faces(2)[0] sage: f1.normal_cone() - A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 1 vertex, 2 rays, 1 line + A 3-dimensional polyhedron in ZZ^3 defined as + the convex hull of 1 vertex, 2 rays, 1 line sage: f2.normal_cone() - A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 1 vertex, 1 ray, 1 line + A 2-dimensional polyhedron in ZZ^3 defined as + the convex hull of 1 vertex, 1 ray, 1 line sage: f3.normal_cone() - A 1-dimensional polyhedron in ZZ^3 defined as the convex hull of 1 vertex and 1 line + A 1-dimensional polyhedron in ZZ^3 defined as + the convex hull of 1 vertex and 1 line Normal cones are only defined for non-empty faces:: @@ -941,8 +941,8 @@ def affine_tangent_cone(self): sage: half_plane_in_space = Polyhedron(ieqs=[(0,1,0,0)], eqns=[(0,0,0,1)]) sage: line = half_plane_in_space.faces(1)[0]; line - A 1-dimensional face - of a Polyhedron in QQ^3 defined as the convex hull of 1 vertex and 1 line + A 1-dimensional face of a + Polyhedron in QQ^3 defined as the convex hull of 1 vertex and 1 line sage: T_line = line.affine_tangent_cone() sage: T_line == half_plane_in_space True @@ -954,9 +954,9 @@ def affine_tangent_cone(self): sage: T_edge = edge.affine_tangent_cone() sage: T_edge.Vrepresentation() (A line in the direction (0, 1, 0), - A ray in the direction (0, 0, 1), - A vertex at (1, 0, -1), - A ray in the direction (-1, 0, 0)) + A ray in the direction (0, 0, 1), + A vertex at (1, 0, -1), + A ray in the direction (-1, 0, 0)) TESTS: @@ -1034,9 +1034,9 @@ def combinatorial_face_to_polyhedral_face(polyhedron, combinatorial_face): INPUT: - ``polyhedron`` -- a polyhedron containing ``combinatorial_face`` - - ``combinatorial_face`` -- a ``CombinatorialFace`` + - ``combinatorial_face`` -- a :class:`CombinatorialFace` - OUTPUT: a ``PolyhedronFace``. + OUTPUT: a :class:`PolyhedronFace`. EXAMPLES:: @@ -1059,9 +1059,9 @@ def combinatorial_face_to_polyhedral_face(polyhedron, combinatorial_face): 0 sage: polytopes.simplex(backend='cdd').equations()[0].index() 4 - sage: polytopes.simplex(backend='normaliz').equations()[0].index() # optional - pynormaliz + sage: polytopes.simplex(backend='normaliz').equations()[0].index() # optional - pynormaliz 4 - sage: polytopes.simplex(backend='polymake').equations()[0].index() # optional - jupymake + sage: polytopes.simplex(backend='polymake').equations()[0].index() # optional - jupymake 4 """ V_indices = combinatorial_face.ambient_V_indices() diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py index f621f9329ff..5a39dcab511 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) # optional - 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))) # optional - sage.combinat + sage: P = project_points(*V) # optional - sage.combinat + sage: for i in range(21): # optional - 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) ] # 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 ....: for j in range(len(V)): ....: assert (V[i]-V[j]).norm() == (P[i]-P[j]).norm() @@ -412,7 +412,7 @@ def gale_transform_to_primal(vectors, base_ring=None, backend=None): (-55, 0, 0), (0, -55, 0), (0, 0, -55)] - sage: gale_transform_to_primal(p, backend='normaliz') # optional - pynormaliz + sage: gale_transform_to_primal(p, backend='normaliz') # optional - pynormaliz [(16, -35, 54), (24, 10, 31), (-15, 50, -60), @@ -515,15 +515,15 @@ 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: octagon = polytopes.regular_polygon(8) # optional - sage.rings.number_field + sage: octagon # optional - sage.rings.number_field 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() # optional - sage.rings.number_field 8 - sage: v = octagon.volume() # optional - sage.rings.number_field - sage: v # optional - sage.rings.number_field + sage: v = octagon.volume() # optional - sage.rings.number_field + sage: v # optional - sage.rings.number_field 2.828427124746190? - sage: v == 2*QQbar(2).sqrt() # optional - sage.rings.number_field + sage: v == 2*QQbar(2).sqrt() # optional - sage.rings.number_field True Its non exact version:: @@ -537,14 +537,14 @@ def regular_polygon(self, n, exact=True, base_ring=None, backend=None): TESTS:: - sage: octagon = polytopes.regular_polygon(8, backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field - sage: octagon # optional - pynormaliz # optional - sage.rings.number_field + sage: octagon = polytopes.regular_polygon(8, backend='normaliz') # optional - pynormaliz sage.rings.number_field + sage: octagon # optional - pynormaliz sage.rings.number_field A 2-dimensional polyhedron in AA^2 defined as the convex hull of 8 vertices - sage: octagon.n_vertices() # optional - pynormaliz # optional - sage.rings.number_field + sage: octagon.n_vertices() # optional - pynormaliz sage.rings.number_field 8 - sage: octagon.volume() # optional - pynormaliz # optional - sage.rings.number_field + sage: octagon.volume() # optional - pynormaliz sage.rings.number_field 2*a - sage: TestSuite(octagon).run() # long time # optional - sage.rings.number_field + sage: TestSuite(octagon).run() # long time # optional - sage.rings.number_field sage: TestSuite(polytopes.regular_polygon(5, exact=False)).run() """ n = ZZ(n) @@ -609,8 +609,8 @@ def Birkhoff_polytope(self, n, backend=None): TESTS:: - sage: b4norm = polytopes.Birkhoff_polytope(4,backend='normaliz') # optional - pynormaliz - sage: TestSuite(b4norm).run() # optional - pynormaliz + sage: b4norm = polytopes.Birkhoff_polytope(4,backend='normaliz') # optional - pynormaliz + sage: TestSuite(b4norm).run() # optional - pynormaliz sage: TestSuite(polytopes.Birkhoff_polytope(3)).run() """ from itertools import permutations @@ -678,14 +678,14 @@ 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) # optional - sage.rings.number_field + sage: s3.volume() == sqrt(3+1) / factorial(3) # optional - sage.rings.number_field True TESTS:: - sage: s6norm = polytopes.simplex(6,backend='normaliz') # optional - pynormaliz - sage: TestSuite(s6norm).run() # optional - pynormaliz + sage: s6norm = polytopes.simplex(6,backend='normaliz') # optional - pynormaliz + sage: TestSuite(s6norm).run() # optional - pynormaliz sage: TestSuite(polytopes.simplex(5)).run() """ verts = list((ZZ**(dim + 1)).basis()) @@ -716,47 +716,47 @@ 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() # optional - sage.rings.number_field + sage: ico.f_vector() # optional - sage.rings.number_field (1, 12, 30, 20, 1) - sage: ico.volume() # optional - sage.rings.number_field + sage: ico.volume() # optional - 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) # optional - sage.groups + sage: ico.base_ring() # optional - sage.groups Real Double Field - sage: ico.volume() # known bug (trac 18214) # optional - sage.groups + sage: ico.volume() # known bug (trac 18214) # optional - sage.groups 2.181694990... A version using `AA `:: - sage: ico = polytopes.icosahedron(base_ring=AA) # long time # optional - sage.rings.number_field # optional - sage.groups - sage: ico.base_ring() # long time # optional - sage.rings.number_field # optional - sage.groups + 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 Algebraic Real Field - sage: ico.volume() # long time # optional - sage.rings.number_field # optional - sage.groups + sage: ico.volume() # long time # optional - sage.rings.number_field sage.groups 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) # optional - 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 # optional - sage.rings.number_field # optional - sage.groups - sage: ico.f_vector() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups + 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 (1, 12, 30, 20, 1) - sage: ico.volume() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups + sage: ico.volume() # optional - pynormaliz sage.rings.number_field sage.groups 5/12*sqrt5 + 5/4 - sage: TestSuite(ico).run() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups + sage: TestSuite(ico).run() # optional - pynormaliz sage.rings.number_field sage.groups - 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) # optional - sage.groups + sage: TestSuite(ico).run(skip="_test_lawrence") # optional - sage.groups """ if base_ring is None and exact: @@ -798,31 +798,31 @@ def dodecahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: d12 = polytopes.dodecahedron() # optional - sage.rings.number_field # optional - sage.groups - sage: d12.f_vector() # optional - sage.rings.number_field # optional - sage.groups + sage: d12 = polytopes.dodecahedron() # optional - sage.rings.number_field sage.groups + sage: d12.f_vector() # optional - sage.rings.number_field sage.groups (1, 20, 30, 12, 1) - sage: d12.volume() # optional - sage.rings.number_field # optional - sage.groups + sage: d12.volume() # optional - sage.rings.number_field sage.groups -176*sqrt5 + 400 - sage: numerical_approx(_) # optional - sage.rings.number_field # optional - sage.groups + sage: numerical_approx(_) # optional - sage.rings.number_field sage.groups 6.45203596003699 - sage: d12 = polytopes.dodecahedron(exact=False) # optional - sage.groups - sage: d12.base_ring() # optional - sage.groups + sage: d12 = polytopes.dodecahedron(exact=False) # optional - sage.groups + sage: d12.base_ring() # optional - 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 # optional - sage.groups + sage: polytopes.dodecahedron(base_ring=QQ) # optional - sage.symbolic sage.groups 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 # optional - sage.rings.number_field # optional - sage.groups - sage: d12.f_vector() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups + 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 (1, 20, 30, 12, 1) - sage: TestSuite(d12).run() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups + sage: TestSuite(d12).run() # optional - pynormaliz sage.rings.number_field sage.groups """ return self.icosahedron(exact=exact, base_ring=base_ring, backend=backend).polar() @@ -847,17 +847,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() # optional - sage.rings.number_field + sage: sr.f_vector() # optional - sage.rings.number_field (1, 24, 48, 26, 1) - sage: sr.volume() # optional - sage.rings.number_field + sage: sr.volume() # optional - 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) # optional - 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) # optional - sage.rings.number_field 18 Its non exact version:: @@ -871,12 +871,12 @@ 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: sr = polytopes.small_rhombicuboctahedron(backend='normaliz') # optional - sage.rings.number_field pynormaliz + sage: sr.f_vector() # optional - sage.rings.number_field pynormaliz (1, 24, 48, 26, 1) - sage: sr.volume() # optional - sage.rings.number_field pynormaliz + sage: sr.volume() # optional - sage.rings.number_field pynormaliz 80/3*sqrt2 + 32 - sage: TestSuite(sr).run() # long time # optional - sage.rings.number_field pynormaliz + sage: TestSuite(sr).run() # long time # optional - sage.rings.number_field pynormaliz """ if base_ring is None and exact: from sage.rings.number_field.number_field import QuadraticField @@ -918,8 +918,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 ~ 3sec # optional - sage.rings.number_field + sage: gr.f_vector() # long time # optional - sage.rings.number_field (1, 48, 72, 26, 1) A faster implementation is obtained by setting ``exact=False``:: @@ -1040,8 +1040,8 @@ def cuboctahedron(self, backend=None): TESTS:: - sage: co_norm = polytopes.cuboctahedron(backend='normaliz') # optional - pynormaliz - sage: TestSuite(co_norm).run() # optional - pynormaliz + sage: co_norm = polytopes.cuboctahedron(backend='normaliz') # optional - pynormaliz + sage: TestSuite(co_norm).run() # optional - pynormaliz """ v = [[0, -1, -1], [0, 1, -1], [0, -1, 1], [0, 1, 1], [-1, -1, 0], [1, -1, 0], [-1, 1, 0], [1, 1, 0], @@ -1072,28 +1072,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() # optional - sage.rings.number_field + sage: co.f_vector() # optional - 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) # optional - 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) # optional - sage.rings.number_field 6 Some more computation:: - sage: co.volume() # optional - sage.rings.number_field + sage: co.volume() # optional - sage.rings.number_field 56/3*sqrt2 - 56/3 TESTS:: - sage: co = polytopes.truncated_cube(backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field - sage: co.f_vector() # optional - pynormaliz # optional - sage.rings.number_field + sage: co = polytopes.truncated_cube(backend='normaliz') # optional - pynormaliz sage.rings.number_field + sage: co.f_vector() # optional - pynormaliz sage.rings.number_field (1, 24, 36, 14, 1) - sage: TestSuite(co).run() # optional - pynormaliz # optional - sage.rings.number_field + sage: TestSuite(co).run() # optional - pynormaliz sage.rings.number_field """ if base_ring is None and exact: @@ -1150,8 +1150,8 @@ def tetrahedron(self, backend=None): TESTS:: - sage: t_norm = polytopes.tetrahedron(backend='normaliz') # optional - pynormaliz - sage: TestSuite(t_norm).run() # optional - pynormaliz + sage: t_norm = polytopes.tetrahedron(backend='normaliz') # optional - pynormaliz + sage: TestSuite(t_norm).run() # optional - pynormaliz """ v = [[0, 0, 0], [1, 0, 1], [1, 1, 0], [0, 1, 1]] return Polyhedron(vertices=v, base_ring=ZZ, backend=backend) @@ -1192,8 +1192,8 @@ def truncated_tetrahedron(self, backend=None): TESTS:: - sage: tt_norm = polytopes.truncated_tetrahedron(backend='normaliz') # optional - pynormaliz - sage: TestSuite(tt_norm).run() # optional - pynormaliz + sage: tt_norm = polytopes.truncated_tetrahedron(backend='normaliz') # optional - pynormaliz + sage: TestSuite(tt_norm).run() # optional - pynormaliz """ v = [(3,1,1), (1,3,1), (1,1,3), (-3,-1,1), (-1,-3,1), (-1,-1,3), @@ -1218,22 +1218,22 @@ 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() # optional - sage.combinat + sage: co.f_vector() # optional - sage.combinat (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) # optional - sage.combinat 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) # optional - sage.combinat 8 Some more computation:: - sage: co.volume() # optional - sage.combinat + sage: co.volume() # optional - sage.combinat 32 - sage: co.ehrhart_polynomial() # optional - latte_int # optional - sage.combinat + sage: co.ehrhart_polynomial() # optional - latte_int sage.combinat 32*t^3 + 18*t^2 + 6*t + 1 TESTS:: @@ -1280,8 +1280,8 @@ def octahedron(self, backend=None): TESTS:: - sage: o_norm = polytopes.octahedron(backend='normaliz') # optional - pynormaliz - sage: TestSuite(o_norm).run() # optional - pynormaliz + sage: o_norm = polytopes.octahedron(backend='normaliz') # optional - pynormaliz + sage: TestSuite(o_norm).run() # optional - pynormaliz """ v = [[0, 0, -1], [0, 0, 1], [1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0]] @@ -1313,14 +1313,14 @@ 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: sc_inexact = polytopes.snub_cube(exact=False); sc_inexact # optional - sage.groups 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() # optional - sage.groups (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: 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 (1, 24, 60, 38, 1) - sage: sorted(sc_exact.vertices()) # long time # optional - sage.groups sage.rings.number_field + sage: sorted(sc_exact.vertices()) # long time # optional - sage.groups sage.rings.number_field [A vertex at (-1, -z, -z^2), A vertex at (-1, -z^2, z), A vertex at (-1, z^2, -z), @@ -1345,13 +1345,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) # long time # optional - sage.groups sage.rings.number_field 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 sage.groups sage.rings.number_field + sage: sc.f_vector() # optional - pynormaliz sage.groups sage.rings.number_field (1, 24, 60, 38, 1) """ @@ -1416,34 +1416,36 @@ def buckyball(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: bb = polytopes.buckyball() # long time - 6secs # optional - sage.groups # optional - sage.rings.number_field - sage: bb.f_vector() # long time # optional - sage.groups # optional - sage.rings.number_field + 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 (1, 60, 90, 32, 1) - sage: bb.base_ring() # long time # optional - sage.groups # optional - sage.rings.number_field - Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? + sage: bb.base_ring() # long time # optional - 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) # optional - sage.groups + sage: bb.f_vector() # optional - sage.groups (1, 60, 90, 32, 1) - sage: bb.base_ring() # optional - sage.groups + sage: bb.base_ring() # optional - 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) # optional - 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) # optional - sage.groups 20 TESTS:: - sage: bb = polytopes.buckyball(backend='normaliz') # optional - sage.groups # optional - sage.rings.number_field # optional - pynormaliz - sage: bb.f_vector() # optional - sage.groups # optional - sage.rings.number_field # optional - pynormaliz + 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 (1, 60, 90, 32, 1) - sage: bb.base_ring() # optional - sage.groups # optional - sage.rings.number_field # optional - pynormaliz - Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? + sage: bb.base_ring() # optional - pynormaliz sage.groups sage.rings.number_field + Number Field in sqrt5 with defining polynomial x^2 - 5 + with sqrt5 = 2.236067977499790? """ return self.icosahedron(exact=exact, base_ring=base_ring, backend=backend).truncation() @@ -1465,25 +1467,26 @@ def icosidodecahedron(self, exact=True, backend=None): EXAMPLES:: - sage: id = polytopes.icosidodecahedron() # optional - sage.rings.number_field # optional - sage.groups - sage: id.f_vector() # optional - sage.rings.number_field # optional - sage.groups + sage: id = polytopes.icosidodecahedron() # optional - sage.rings.number_field sage.groups + sage: id.f_vector() # optional - sage.rings.number_field sage.groups (1, 30, 60, 32, 1) TESTS:: - sage: id = polytopes.icosidodecahedron(exact=False); id # optional - sage.rings.number_field # optional - sage.groups + sage: id = polytopes.icosidodecahedron(exact=False); id # optional - sage.rings.number_field sage.groups 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 # optional - sage.groups + sage: TestSuite(id).run(skip=["_test_is_combinatorially_isomorphic", # optional - sage.rings.number_field sage.groups ....: "_test_product", ....: "_test_pyramid", ....: "_test_lawrence"]) - sage: id = polytopes.icosidodecahedron(backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups - sage: id.f_vector() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups + 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 (1, 30, 60, 32, 1) - sage: id.base_ring() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups - Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? - sage: TestSuite(id).run() # long time # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups + sage: id.base_ring() # optional - pynormaliz sage.rings.number_field sage.groups + 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 """ from sage.rings.number_field.number_field import QuadraticField from itertools import product @@ -1530,10 +1533,11 @@ def icosidodecahedron_V2(self, exact=True, base_ring=None, backend=None): EXAMPLES:: sage: id = polytopes.icosidodecahedron_V2() # long time - 6secs - sage: id.f_vector() # long time + sage: id.f_vector() # long time (1, 30, 60, 32, 1) - sage: id.base_ring() # long time - Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? + sage: id.base_ring() # long time + Number Field in sqrt5 with defining polynomial x^2 - 5 + with sqrt5 = 2.236067977499790? A much faster implementation using floating point approximations:: @@ -1552,12 +1556,13 @@ 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: id = polytopes.icosidodecahedron_V2(backend='normaliz') # optional - pynormaliz + sage: id.f_vector() # optional - pynormaliz (1, 30, 60, 32, 1) - sage: id.base_ring() # optional - pynormaliz - Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? - sage: TestSuite(id).run() # optional - pynormaliz, long time + sage: id.base_ring() # optional - pynormaliz + Number Field in sqrt5 with defining polynomial x^2 - 5 + with sqrt5 = 2.236067977499790? + sage: TestSuite(id).run() # long time # optional - pynormaliz """ if base_ring is None and exact: from sage.rings.number_field.number_field import QuadraticField @@ -1600,24 +1605,25 @@ 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() # optional - sage.rings.number_field + sage: td.f_vector() # optional - sage.rings.number_field (1, 60, 90, 32, 1) - sage: td.base_ring() # optional - sage.rings.number_field - Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? + sage: td.base_ring() # optional - 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) # optional - 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) # optional - sage.rings.number_field 12 The faster implementation using floating point approximations does not fully work unfortunately, see https://github.com/cddlib/cddlib/pull/7 for a detailed discussion of this case:: - sage: td = polytopes.truncated_dodecahedron(exact=False) # random + sage: td = polytopes.truncated_dodecahedron(exact=False) # random doctest:warning ... UserWarning: This polyhedron data is numerically complicated; cdd @@ -1633,11 +1639,12 @@ def truncated_dodecahedron(self, exact=True, base_ring=None, backend=None): TESTS:: - sage: td = polytopes.truncated_dodecahedron(backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field - sage: td.f_vector() # optional - pynormaliz # optional - sage.rings.number_field + sage: td = polytopes.truncated_dodecahedron(backend='normaliz') # optional - pynormaliz sage.rings.number_field + sage: td.f_vector() # optional - pynormaliz sage.rings.number_field (1, 60, 90, 32, 1) - sage: td.base_ring() # optional - pynormaliz # optional - sage.rings.number_field - Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? + sage: td.base_ring() # optional - pynormaliz sage.rings.number_field + Number Field in sqrt5 with defining polynomial x^2 - 5 + with sqrt5 = 2.236067977499790? """ if base_ring is None and exact: @@ -1736,8 +1743,8 @@ def Kirkman_icosahedron(self, backend=None): TESTS:: - sage: ki_norm = polytopes.Kirkman_icosahedron(backend='normaliz') # optional - pynormaliz - sage: TestSuite(ki_norm).run() # optional - pynormaliz + sage: ki_norm = polytopes.Kirkman_icosahedron(backend='normaliz') # optional - pynormaliz + sage: TestSuite(ki_norm).run() # optional - pynormaliz """ vertices = [[9, 6, 6], [-9, 6, 6], [9, -6, 6], [9, 6, -6], [-9, -6, 6], [-9, 6, -6], [9, -6, -6], [-9, -6, -6], @@ -1769,10 +1776,11 @@ def rhombicosidodecahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: sage: rid = polytopes.rhombicosidodecahedron() # long time - 6secs - sage: rid.f_vector() # long time + sage: rid.f_vector() # long time (1, 60, 120, 62, 1) - sage: rid.base_ring() # long time - Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? + sage: rid.base_ring() # long time + Number Field in sqrt5 with defining polynomial x^2 - 5 + with sqrt5 = 2.236067977499790? A much faster implementation using floating point approximations:: @@ -1793,11 +1801,12 @@ 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: rid = polytopes.rhombicosidodecahedron(backend='normaliz') # optional - pynormaliz + sage: rid.f_vector() # optional - pynormaliz (1, 60, 120, 62, 1) - sage: rid.base_ring() # optional - pynormaliz - Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? + sage: rid.base_ring() # optional - pynormaliz + Number Field in sqrt5 with defining polynomial x^2 - 5 + with sqrt5 = 2.236067977499790? """ if base_ring is None and exact: @@ -1845,11 +1854,12 @@ def truncated_icosidodecahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: ti = polytopes.truncated_icosidodecahedron() # long time - sage: ti.f_vector() # long time + sage: ti = polytopes.truncated_icosidodecahedron() # long time + sage: ti.f_vector() # long time (1, 120, 180, 62, 1) - sage: ti.base_ring() # long time - Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790? + sage: ti.base_ring() # long time + Number Field in sqrt5 with defining polynomial x^2 - 5 + with sqrt5 = 2.236067977499790? The implementation using floating point approximations is much faster:: @@ -1924,17 +1934,20 @@ def snub_dodecahedron(self, base_ring=None, backend=None, verbose=False): Only the backend using the optional normaliz package can construct the snub dodecahedron in reasonable time:: - sage: sd = polytopes.snub_dodecahedron(base_ring=AA, backend='normaliz') # optional - pynormaliz, long time - sage: sd.f_vector() # optional - pynormaliz, long time + sage: sd = polytopes.snub_dodecahedron(base_ring=AA, # optional - pynormaliz, long time + ....: backend='normaliz') + sage: sd.f_vector() # optional - pynormaliz, long time (1, 60, 150, 92, 1) - sage: sd.base_ring() # optional - pynormaliz, long time + sage: sd.base_ring() # optional - pynormaliz, long time Algebraic Real Field Its facets are 80 triangles and 12 pentagons:: - sage: sum(1 for f in sd.facets() if len(f.vertices()) == 3) # optional - pynormaliz, long time + sage: sum(1 for f in sd.facets() # optional - pynormaliz, long time + ....: if len(f.vertices()) == 3) 80 - sage: sum(1 for f in sd.facets() if len(f.vertices()) == 5) # optional - pynormaliz, long time + sage: sum(1 for f in sd.facets() # optional - pynormaliz, long time + ....: if len(f.vertices()) == 5) 12 TESTS: @@ -2009,8 +2022,8 @@ def twenty_four_cell(self, backend=None): TESTS:: - sage: tfcell = polytopes.twenty_four_cell(backend='normaliz') # optional - pynormaliz - sage: TestSuite(tfcell).run() # optional - pynormaliz + sage: tfcell = polytopes.twenty_four_cell(backend='normaliz') # optional - pynormaliz + sage: TestSuite(tfcell).run() # optional - pynormaliz """ q12 = QQ((1, 2)) verts = list(itertools.product([q12, -q12], repeat=4)) @@ -2042,7 +2055,7 @@ def runcitruncated_six_hundred_cell(self, exact=True, backend=None): EXAMPLES:: - sage: polytopes.runcitruncated_six_hundred_cell(backend='normaliz') # not tested - very long time + sage: polytopes.runcitruncated_six_hundred_cell(backend='normaliz') # not tested - very long time A 4-dimensional polyhedron in AA^4 defined as the convex hull of 7200 vertices """ @@ -2071,7 +2084,8 @@ def cantitruncated_six_hundred_cell(self, exact=True, backend=None): EXAMPLES:: - sage: polytopes.cantitruncated_six_hundred_cell(exact=True,backend='normaliz') # not tested - very long time + sage: polytopes.cantitruncated_six_hundred_cell(exact=True, # not tested - very long time + ....: backend='normaliz') A 4-dimensional polyhedron in AA^4 defined as the convex hull of 7200 vertices """ return self.generalized_permutahedron(['H', 4], point=[1, 1, 1, 0], exact=exact, backend=backend, regular=True) @@ -2099,7 +2113,8 @@ def bitruncated_six_hundred_cell(self, exact=True, backend=None): EXAMPLES:: - sage: polytopes.runcinated_six_hundred_cell(exact=True,backend='normaliz') # not tested - very long time + sage: polytopes.runcinated_six_hundred_cell(exact=True, # not tested - very long time + ....: backend='normaliz') A 4-dimensional polyhedron in AA^4 defined as the convex hull of 3600 vertices """ return self.generalized_permutahedron(['H', 4], point=[0, 1, 1, 0], exact=exact, backend=backend, regular=True) @@ -2127,7 +2142,7 @@ def cantellated_six_hundred_cell(self, exact=False, backend=None): EXAMPLES:: - sage: polytopes.cantellated_six_hundred_cell() # not tested - very long time + sage: polytopes.cantellated_six_hundred_cell() # not tested - very long time doctest:warning ... UserWarning: This polyhedron data is numerically complicated; cdd @@ -2139,7 +2154,8 @@ def cantellated_six_hundred_cell(self, exact=False, backend=None): It is possible to use the backend ``'normaliz'`` to get an exact representation:: - sage: polytopes.cantellated_six_hundred_cell(exact=True,backend='normaliz') # not tested - long time + sage: polytopes.cantellated_six_hundred_cell(exact=True, # not tested - long time + ....: backend='normaliz') A 4-dimensional polyhedron in AA^4 defined as the convex hull of 3600 vertices """ return self.generalized_permutahedron(['H', 4], point=[1, 0, 1, 0], exact=exact, backend=backend, regular=True) @@ -2166,7 +2182,7 @@ def truncated_six_hundred_cell(self, exact=False, backend=None): EXAMPLES:: - sage: polytopes.truncated_six_hundred_cell() # not tested - long time + sage: polytopes.truncated_six_hundred_cell() # not tested - long time A 4-dimensional polyhedron in RDF^4 defined as the convex hull of 1440 vertices It is possible to use the backend ``'normaliz'`` to get an exact @@ -2200,7 +2216,7 @@ def rectified_six_hundred_cell(self, exact=True, backend=None): EXAMPLES:: - sage: polytopes.rectified_six_hundred_cell(backend='normaliz') # not tested - long time ~14sec + sage: polytopes.rectified_six_hundred_cell(backend='normaliz') # not tested - long time ~14sec A 4-dimensional polyhedron in AA^4 defined as the convex hull of 720 vertices """ return self.generalized_permutahedron(['H', 4], point=[0, 1, 0, 0], exact=exact, backend=backend, regular=True) @@ -2226,22 +2242,22 @@ def six_hundred_cell(self, exact=False, backend=None): EXAMPLES:: - sage: p600 = polytopes.six_hundred_cell() # optional - sage.groups - sage: p600 # optional - sage.groups + sage: p600 = polytopes.six_hundred_cell(); p600 # optional - 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 # optional - 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) # not tested - very long time, optional - sage.groups + sage: len(list(p600.bounded_edges())) # not tested - very long time, optional - sage.groups 720 TESTS:: - sage: p600 = polytopes.six_hundred_cell(exact=True, backend='normaliz') # optional - pynormaliz # optional - sage.groups # optional - sage.rings.number_field - sage: len(list(p600.bounded_edges())) # optional - pynormaliz, long time # optional - sage.groups # optional - sage.rings.number_field + sage: p600 = polytopes.six_hundred_cell(exact=True, # optional - pynormaliz sage.groups sage.rings.number_field + ....: backend='normaliz') + sage: len(list(p600.bounded_edges())) # long time # optional - pynormaliz sage.groups sage.rings.number_field 720 """ if exact: @@ -2297,8 +2313,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 # optional - sage.rings.number_field - sage: gap_norm # optional - pynormaliz # optional - sage.rings.number_field + sage: gap_norm = polytopes.grand_antiprism(backend='normaliz') # optional - pynormaliz sage.rings.number_field + sage: gap_norm # optional - pynormaliz 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 @@ -2454,21 +2470,21 @@ def hypersimplex(self, dim, k, project=False, backend=None): EXAMPLES:: - sage: h_4_2 = polytopes.hypersimplex(4, 2) - sage: h_4_2 + sage: h_4_2 = polytopes.hypersimplex(4, 2) # optional - sage.combinat + sage: h_4_2 # optional - sage.combinat A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 6 vertices - sage: h_4_2.f_vector() + sage: h_4_2.f_vector() # optional - sage.combinat (1, 6, 12, 8, 1) - sage: h_4_2.ehrhart_polynomial() # optional - latte_int + sage: h_4_2.ehrhart_polynomial() # optional - latte_int sage.combinat 2/3*t^3 + 2*t^2 + 7/3*t + 1 - sage: TestSuite(h_4_2).run() + sage: TestSuite(h_4_2).run() # optional - sage.combinat - sage: h_7_3 = polytopes.hypersimplex(7, 3, project=True) - sage: h_7_3 + sage: h_7_3 = polytopes.hypersimplex(7, 3, project=True) # optional - sage.combinat + sage: h_7_3 # optional - sage.combinat A 6-dimensional polyhedron in RDF^6 defined as the convex hull of 35 vertices - sage: h_7_3.f_vector() + sage: h_7_3.f_vector() # optional - sage.combinat (1, 35, 210, 350, 245, 84, 14, 1) - sage: TestSuite(h_7_3).run(skip=["_test_pyramid", "_test_lawrence"]) + sage: TestSuite(h_7_3).run(skip=["_test_pyramid", "_test_lawrence"]) # optional - sage.combinat """ verts = Permutations([0] * (dim - k) + [1] * k).list() if project: @@ -2516,7 +2532,7 @@ def permutahedron(self, n, project=False, backend=None): A 3-dimensional polyhedron in RDF^3 defined as the convex hull of 24 vertices sage: perm4.plot() # optional - sage.plot Graphics3d Object - sage: perm4.graph().is_isomorphic(graphs.BubbleSortGraph(4)) # optional - sage.graphs + sage: perm4.graph().is_isomorphic(graphs.BubbleSortGraph(4)) # optional - sage.graphs True As both Hrepresentation an Vrepresentation are known, the permutahedron can be set @@ -2594,32 +2610,35 @@ 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 # optional - 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]); perm_a3_011 # optional - sage.combinat + sage: perm_a3_011 = polytopes.generalized_permutahedron(['A',3], [0,1,1]) # optional - sage.combinat + 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]); perm_a3_110 # optional - sage.combinat + sage: perm_a3_110 = polytopes.generalized_permutahedron(['A',3], [1,1,0]) # optional - sage.combinat + 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) # optional - sage.combinat True - sage: perm_a3_101 = polytopes.generalized_permutahedron(['A',3],[1,0,1]); perm_a3_101 # optional - sage.combinat + sage: perm_a3_101 = polytopes.generalized_permutahedron(['A',3], [1,0,1]) # optional - sage.combinat + 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) # optional - sage.combinat False - sage: perm_a3_011.f_vector() # optional - sage.combinat + sage: perm_a3_011.f_vector() # optional - sage.combinat (1, 12, 18, 8, 1) - sage: perm_a3_101.f_vector() # optional - sage.combinat + sage: perm_a3_101.f_vector() # optional - sage.combinat (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]) # optional - sage.combinat + sage: perm_a2.vertices() # optional - sage.combinat (A vertex at (-1, -1), A vertex at (-1, 0), A vertex at (0, -1), @@ -2629,18 +2648,20 @@ 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]); perm_b3 # long time # optional - sage.combinat # optional - 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 + sage: perm_b3 = polytopes.generalized_permutahedron(['B',3]) # long time # optional - sage.combinat sage.rings.number_field + sage: perm_b3 + 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 Setting ``regular=True`` applies a linear transformation to get isometric vertex figures and the result is inscribed. This cannot be done using rational coordinates. We first do the computations using floating point approximations (``RDF``):: - sage: perm_a2_inexact = polytopes.generalized_permutahedron(['A',2], exact=False) # optional - sage.combinat - sage: sorted(perm_a2_inexact.vertices()) # optional - sage.combinat + sage: perm_a2_inexact = polytopes.generalized_permutahedron( # optional - sage.combinat + ....: ['A',2], exact=False) + sage: sorted(perm_a2_inexact.vertices()) # optional - sage.combinat [A vertex at (-1.0, -1.0), A vertex at (-1.0, 0.0), A vertex at (0.0, -1.0), @@ -2648,9 +2669,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(['A',2], exact=False, # optional - sage.combinat - ....: regular=True) - sage: sorted(perm_a2_inexact_reg.vertices()) # optional - sage.combinat + sage: perm_a2_inexact_reg = polytopes.generalized_permutahedron( # optional - sage.combinat + ....: ['A',2], exact=False, regular=True) + sage: sorted(perm_a2_inexact_reg.vertices()) # optional - sage.combinat [A vertex at (-1.0, 0.0), A vertex at (-0.5, -0.8660254038), A vertex at (-0.5, 0.8660254038), @@ -2660,8 +2681,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(['A',2], regular=True) # optional - sage.combinat # optional - sage.rings.number_field - sage: V = sorted(perm_a2_reg.vertices()); V # random # optional - sage.combinat # optional - sage.rings.number_field + sage: perm_a2_reg = polytopes.generalized_permutahedron( # optional - 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 [A vertex at (-1, 0), A vertex at (-1/2, -0.866025403784439?), A vertex at (-1/2, 0.866025403784439?), @@ -2672,60 +2694,62 @@ 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 # optional - sage.rings.number_field + sage: for v in V: # optional - sage.combinat sage.rings.number_field ....: for x in v: ....: x.exactify() - sage: V # optional - sage.combinat # optional - sage.rings.number_field + sage: V # optional - 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 # optional - sage.rings.number_field + sage: perm_a2_reg.is_inscribed() # optional - sage.combinat sage.rings.number_field True Larger examples take longer:: - sage: perm_a3_reg = polytopes.generalized_permutahedron(['A',3], regular=True); perm_a3_reg # long time # optional - sage.rings.number_field # optional - sage.combinat + sage: perm_a3_reg = polytopes.generalized_permutahedron( # long time # optional - sage.rings.number_field sage.combinat + ....: ['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 # optional - sage.combinat + sage: perm_a3_reg.is_inscribed() # long time # optional - sage.rings.number_field sage.combinat True - sage: perm_b3_reg = polytopes.generalized_permutahedron(['B',3], regular=True); perm_b3_reg # not tested # optional - sage.rings.number_field # optional - sage.combinat # long time (12sec on 64 bits) + sage: perm_b3_reg = polytopes.generalized_permutahedron( # not tested # optional - sage.rings.number_field sage.combinat # long time (12sec on 64 bits) + ....: ['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 # optional - sage.combinat + sage: perm_a3_reg_nf = polytopes.generalized_permutahedron( # optional - sage.rings.number_field sage.combinat ....: ['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 # optional - sage.combinat + sage: perm_a3_reg_nf.is_inscribed() # optional - sage.rings.number_field sage.combinat True - sage: perm_b3_reg_nf = polytopes.generalized_permutahedron( # long time # optional - sage.rings.number_field # optional - sage.combinat + sage: perm_b3_reg_nf = polytopes.generalized_permutahedron( # long time # optional - sage.rings.number_field sage.combinat ....: ['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 # optional - sage.rings.number_field # optional - sage.combinat + sage: perm_a3_reg_norm = polytopes.generalized_permutahedron( # optional - pynormaliz sage.rings.number_field sage.combinat ....: ['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 # optional - sage.rings.number_field # optional - sage.combinat + sage: perm_a3_reg_norm.is_inscribed() # optional - pynormaliz sage.rings.number_field sage.combinat True - sage: perm_b3_reg_norm = polytopes.generalized_permutahedron( # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.combinat + sage: perm_b3_reg_norm = polytopes.generalized_permutahedron( # optional - pynormaliz sage.rings.number_field sage.combinat ....: ['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(['H',3], backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.combinat - sage: perm_h3 # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.combinat - A 3-dimensional polyhedron - in (Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790?)^3 + sage: perm_h3 = polytopes.generalized_permutahedron( # optional - pynormaliz sage.rings.number_field sage.combinat + ....: ['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(['F',4], backend='normaliz') # long time # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.combinat - sage: perm_f4 # long time # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.combinat + sage: perm_f4 = polytopes.generalized_permutahedron( # long time, optional - pynormaliz sage.rings.number_field sage.combinat + ....: ['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 defined as the convex hull of 1152 vertices @@ -2737,7 +2761,7 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula TESTS:: - sage: TestSuite(perm_h3).run() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.combinat + sage: TestSuite(perm_h3).run() # optional - pynormaliz sage.rings.number_field sage.combinat """ from sage.combinat.root_system.coxeter_group import CoxeterGroup try: @@ -2817,7 +2841,7 @@ def omnitruncated_one_hundred_twenty_cell(self, exact=True, backend=None): EXAMPLES:: - sage: polytopes.omnitruncated_one_hundred_twenty_cell(backend='normaliz') # not tested - very long time ~10min + sage: polytopes.omnitruncated_one_hundred_twenty_cell(backend='normaliz') # not tested - very long time ~10min A 4-dimensional polyhedron in AA^4 defined as the convex hull of 14400 vertices """ if not exact: @@ -2850,7 +2874,7 @@ def runcitruncated_one_hundred_twenty_cell(self, exact=False, backend=None): EXAMPLES:: - sage: polytopes.runcitruncated_one_hundred_twenty_cell(exact=False) # not tested - very long time + sage: polytopes.runcitruncated_one_hundred_twenty_cell(exact=False) # not tested - very long time doctest:warning ... UserWarning: This polyhedron data is numerically complicated; cdd @@ -2861,7 +2885,8 @@ def runcitruncated_one_hundred_twenty_cell(self, exact=False, backend=None): It is possible to use the backend ``'normaliz'`` to get an exact representation:: - sage: polytopes.runcitruncated_one_hundred_twenty_cell(exact=True,backend='normaliz') # not tested - very long time + sage: polytopes.runcitruncated_one_hundred_twenty_cell(exact=True, # not tested - very long time + ....: backend='normaliz') A 4-dimensional polyhedron in AA^4 defined as the convex hull of 7200 vertices """ return self.generalized_permutahedron(['H', 4], point=[1, 0, 1, 1], exact=exact, backend=backend, regular=True) @@ -2889,7 +2914,7 @@ def cantitruncated_one_hundred_twenty_cell(self, exact=True, backend=None): EXAMPLES:: - sage: polytopes.cantitruncated_one_hundred_twenty_cell(exact=True,backend='normaliz') # not tested - very long time + sage: polytopes.cantitruncated_one_hundred_twenty_cell(exact=True, backend='normaliz') # not tested - very long time A 4-dimensional polyhedron in AA^4 defined as the convex hull of 7200 vertices """ return self.generalized_permutahedron(['H', 4], point=[0, 1, 1, 1], exact=exact, backend=backend, regular=True) @@ -2917,7 +2942,7 @@ def runcinated_one_hundred_twenty_cell(self, exact=False, backend=None): EXAMPLES:: - sage: polytopes.runcinated_one_hundred_twenty_cell(exact=False) # not tested - very long time + sage: polytopes.runcinated_one_hundred_twenty_cell(exact=False) # not tested - very long time doctest:warning ... UserWarning: This polyhedron data is numerically complicated; cdd could not convert between the inexact V and H representation without loss of data. The resulting object @@ -2927,7 +2952,8 @@ def runcinated_one_hundred_twenty_cell(self, exact=False, backend=None): It is possible to use the backend ``'normaliz'`` to get an exact representation:: - sage: polytopes.runcinated_one_hundred_twenty_cell(exact=True,backend='normaliz') # not tested - very long time + sage: polytopes.runcinated_one_hundred_twenty_cell(exact=True, # not tested - very long time + ....: backend='normaliz') A 4-dimensional polyhedron in AA^4 defined as the convex hull of 2400 vertices """ return self.generalized_permutahedron(['H', 4], point=[1, 0, 0, 1], exact=exact, backend=backend, regular=True) @@ -2955,7 +2981,7 @@ def cantellated_one_hundred_twenty_cell(self, exact=True, backend=None): EXAMPLES:: - sage: polytopes.cantellated_one_hundred_twenty_cell(backend='normaliz') # not tested - long time + sage: polytopes.cantellated_one_hundred_twenty_cell(backend='normaliz') # not tested - long time A 4-dimensional polyhedron in AA^4 defined as the convex hull of 3600 vertices """ return self.generalized_permutahedron(['H', 4], point=[0, 1, 0, 1], exact=exact, backend=backend, regular=True) @@ -2983,7 +3009,7 @@ def truncated_one_hundred_twenty_cell(self, exact=True, backend=None): EXAMPLES:: - sage: polytopes.truncated_one_hundred_twenty_cell(backend='normaliz') # not tested - long time + sage: polytopes.truncated_one_hundred_twenty_cell(backend='normaliz') # not tested - long time A 4-dimensional polyhedron in AA^4 defined as the convex hull of 2400 vertices """ return self.generalized_permutahedron(['H', 4], point=[0, 0, 1, 1], exact=exact, backend=backend, regular=True) @@ -3011,7 +3037,7 @@ def rectified_one_hundred_twenty_cell(self, exact=True, backend=None): EXAMPLES:: - sage: polytopes.rectified_one_hundred_twenty_cell(backend='normaliz') # not tested - long time + sage: polytopes.rectified_one_hundred_twenty_cell(backend='normaliz') # not tested - long time A 4-dimensional polyhedron in AA^4 defined as the convex hull of 1200 vertices """ return self.generalized_permutahedron(['H', 4], point=[0, 0, 1, 0], exact=exact, backend=backend, regular=True) @@ -3046,24 +3072,26 @@ def one_hundred_twenty_cell(self, exact=True, backend=None, construction='coxete sage: polytopes.one_hundred_twenty_cell() # not tested - long time ~15 sec. 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 600 vertices + polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^4 defined as + the convex hull of 600 vertices The ``'normaliz'`` is faster:: sage: P = polytopes.one_hundred_twenty_cell(backend='normaliz'); P # optional - pynormaliz 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 600 vertices + polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^4 defined as + the convex hull of 600 vertices It is also possible to realize it using the generalized permutahedron of type `H_4`:: - sage: polytopes.one_hundred_twenty_cell(backend='normaliz',construction='as_permutahedron') # not tested - long time + sage: polytopes.one_hundred_twenty_cell(backend='normaliz', # not tested - long time + ....: construction='as_permutahedron') A 4-dimensional polyhedron in AA^4 defined as the convex hull of 600 vertices TESTS:: - sage: TestSuite(P).run() # optional - pynormaliz, long time + sage: TestSuite(P).run() # long time, optional - pynormaliz """ if construction == 'coxeter': if not exact: @@ -3151,7 +3179,7 @@ def hypercube(self, dim, intervals=None, backend=None): Return the `0/1`-hypercube of dimension 4:: - sage: z_cube = polytopes.hypercube(4,intervals = 'zero_one') + sage: z_cube = polytopes.hypercube(4, intervals='zero_one') sage: z_cube.vertices()[0] A vertex at (1, 0, 1, 1) sage: z_cube.is_simple() @@ -3160,13 +3188,13 @@ def hypercube(self, dim, intervals=None, backend=None): Integer Ring sage: z_cube.volume() 1 - sage: z_cube.ehrhart_polynomial() # optional - latte_int + sage: z_cube.ehrhart_polynomial() # optional - latte_int t^4 + 4*t^3 + 6*t^2 + 4*t + 1 Return the 4-dimensional combinatorial cube that is the product of [0,3]^4:: - sage: t_cube = polytopes.hypercube(4, intervals = [[0,3]]*4) + sage: t_cube = polytopes.hypercube(4, intervals=[[0,3]]*4) Checking that t_cube is three times the previous `0/1`-cube:: @@ -3194,14 +3222,14 @@ def hypercube(self, dim, intervals=None, backend=None): If the dimension ``dim`` is not equal to the length of intervals, an error is raised:: - sage: u_cube = polytopes.hypercube(2,intervals = [[0,1],[0,2],[0,3]]) + sage: u_cube = polytopes.hypercube(2, intervals=[[0,1],[0,2],[0,3]]) Traceback (most recent call last): ... ValueError: the dimension of the hypercube must match the number of intervals The intervals must be pairs `(a, b)` with `a < b`:: - sage: w_cube = polytopes.hypercube(3, intervals = [[0,1],[3,2],[0,3]]) + sage: w_cube = polytopes.hypercube(3, intervals=[[0,1],[3,2],[0,3]]) Traceback (most recent call last): ... ValueError: each interval must be a pair `(a, b)` with `a < b` @@ -3209,7 +3237,7 @@ def hypercube(self, dim, intervals=None, backend=None): If a string besides 'zero_one' is passed to ``intervals``, return an error:: - sage: v_cube = polytopes.hypercube(3,intervals = 'a_string') + sage: v_cube = polytopes.hypercube(3, intervals='a_string') Traceback (most recent call last): ... ValueError: the only allowed string is 'zero_one' @@ -3219,7 +3247,7 @@ 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') + sage: P1 = polytopes.hypercube(4, intervals, backend='ppl') # optional - pplpy sage: assert P == P1 Check that coercion for input invervals is handled correctly:: @@ -3227,7 +3255,7 @@ def hypercube(self, dim, intervals=None, backend=None): 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') + sage: P = polytopes.hypercube(2, [[1/2, 2], [0, 1.0]], backend='ppl') # optional - pplpy Traceback (most recent call last): ... ValueError: specified backend ppl cannot handle the intervals @@ -3304,13 +3332,13 @@ def cube(self, intervals=None, backend=None): - ``intervals`` -- list (default=None). It takes the following possible inputs: - - If the input is ``None`` (the default), returns the convex hull of - the eight `\pm 1` vectors of length three. + - If the input is ``None`` (the default), returns the convex hull of + the eight `\pm 1` vectors of length three. - - ``'zero_one'`` -- (string). Return the `0/1`-cube. + - ``'zero_one'`` -- (string). Return the `0/1`-cube. - - a list of 3 lists of length 2. The cube will be a product of - these three intervals. + - a list of 3 lists of length 2. The cube will be a product of + these three intervals. - ``backend`` -- the backend to use to create the polytope. @@ -3372,7 +3400,7 @@ def cross_polytope(self, dim, backend=None): TESTS:: - sage: cp = polytopes.cross_polytope(4,backend='normaliz') # optional - pynormaliz + sage: cp = polytopes.cross_polytope(4, backend='normaliz') # optional - pynormaliz sage: TestSuite(cp).run() # optional - pynormaliz :: @@ -3410,19 +3438,19 @@ def parallelotope(self, generators, backend=None): sage: polytopes.parallelotope([ (1,0), (0,1) ]) A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices - sage: polytopes.parallelotope([[1,2,3,4],[0,1,0,7],[3,1,0,2],[0,0,1,0]]) + 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') # 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 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() # optional - 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 1e0345c054f..ad0ad961bf1 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) + sage: P._to_space_separated_string([2, 1/5], RDF) # optional - sage.rings.real_double '2.0 0.2' """ if base_ring: diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 3640e0c524b..1993f17b1cc 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) # optional - sage.rings.number_field Polyhedra in AA^3 sage: Polyhedra(ZZ, 3) Polyhedra in ZZ^3 @@ -96,32 +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') # optional - 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) # optional - 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) # optional - 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 # optional - sage.rings.number_field + 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 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') # optional - pynormaliz Polyhedra in QQ^2 - sage: Polyhedra(SR, 2, backend='normaliz') # optional - pynormaliz # optional - sage.symbolic + sage: Polyhedra(SR, 2, backend='normaliz') # optional - pynormaliz 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 # optional - sage.symbolic + sage: SCR = SR.subring(no_variables=True) # optional - sage.symbolic + sage: Polyhedra(SCR, 2, backend='normaliz') # optional - pynormaliz 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') # optional - sage.symbolic Polyhedra in (Symbolic Constants Subring)^2 """ @@ -208,15 +210,15 @@ class Polyhedra_base(UniqueRepresentation, Parent): - ``backend`` -- string. The name of the backend for computations. There are several backends implemented: - * ``backend="ppl"`` uses the Parma Polyhedra Library + * ``backend="ppl"`` uses the Parma Polyhedra Library - * ``backend="cdd"`` uses CDD + * ``backend="cdd"`` uses CDD - * ``backend="normaliz"`` uses normaliz + * ``backend="normaliz"`` uses normaliz - * ``backend="polymake"`` uses polymake + * ``backend="polymake"`` uses polymake - * ``backend="field"`` a generic Sage implementation + * ``backend="field"`` a generic Sage implementation EXAMPLES:: @@ -270,13 +272,13 @@ 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: P = Polyhedra(AA, 0) # optional - sage.rings.number_field + sage: P.category() # optional - sage.rings.number_field Category of finite enumerated polyhedral sets over Algebraic Real Field - sage: P.list() # optional - sage.rings.number_field + sage: P.list() # optional - sage.rings.number_field [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() # optional - sage.rings.number_field 2 """ if self.ambient_dim(): @@ -380,11 +382,14 @@ def some_elements(self): sage: from sage.geometry.polyhedron.parent import Polyhedra sage: Polyhedra(QQ, 4).some_elements() - [A 3-dimensional polyhedron in QQ^4 defined as the convex hull of 4 vertices, - A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 1 vertex and 4 rays, - A 2-dimensional polyhedron in QQ^4 defined as the convex hull of 2 vertices and 1 ray, + [A 3-dimensional polyhedron in QQ^4 + defined as the convex hull of 4 vertices, + A 4-dimensional polyhedron in QQ^4 + defined as the convex hull of 1 vertex and 4 rays, + A 2-dimensional polyhedron in QQ^4 + defined as the convex hull of 2 vertices and 1 ray, The empty polyhedron in QQ^4] - sage: Polyhedra(ZZ,0).some_elements() + sage: Polyhedra(ZZ, 0).some_elements() [The empty polyhedron in ZZ^0, A 0-dimensional polyhedron in ZZ^0 defined as the convex hull of 1 vertex] """ @@ -413,7 +418,7 @@ def zero(self): sage: from sage.geometry.polyhedron.parent import Polyhedra sage: p = Polyhedra(QQ, 4).zero(); p A 0-dimensional polyhedron in QQ^4 defined as the convex hull of 1 vertex - sage: p+p == p + sage: p + p == p True """ Vrep = [[[self.base_ring().zero()]*self.ambient_dim()], [], []] @@ -443,7 +448,8 @@ def universe(self): sage: from sage.geometry.polyhedron.parent import Polyhedra sage: P = Polyhedra(QQ, 4) sage: P.universe() - A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 1 vertex and 4 lines + A 4-dimensional polyhedron in QQ^4 defined as + the convex hull of 1 vertex and 4 lines sage: P.universe().is_universe() True """ @@ -510,8 +516,8 @@ def _repr_base_ring(self): sage: from sage.geometry.polyhedron.parent import Polyhedra sage: Polyhedra(QQ, 3)._repr_base_ring() 'QQ' - 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()) # optional - sage.rings.number_field + sage: Polyhedra(K, 4)._repr_base_ring() # optional - sage.rings.number_field '(Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)' """ @@ -544,8 +550,8 @@ def _repr_ambient_module(self): sage: from sage.geometry.polyhedron.parent import Polyhedra sage: Polyhedra(QQ, 3)._repr_ambient_module() 'QQ^3' - 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()) # optional - sage.rings.number_field + sage: Polyhedra(K, 4)._repr_ambient_module() # optional - sage.rings.number_field '(Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)^4' """ s = self._repr_base_ring() @@ -600,12 +606,13 @@ 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', return_variable=True) # optional - sage.rings.number_field - 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 # optional - sage.rings.number_field + 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 + ....: 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: Q = Polyhedron(ieqs=[[-499999, 1000000], [1499999, -1000000]]) sage: P = Polyhedron(ieqs=[[0, 1.0], [1.0, -1.0]], base_ring=RDF) @@ -627,11 +634,11 @@ 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: 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 False - sage: q = Q._element_constructor_(p, copy=False) # optional - sage.rings.number_field + sage: q = Q._element_constructor_(p, copy=False) # optional - sage.rings.number_field Traceback (most recent call last): ... ValueError: you need to make a copy when changing the parent @@ -718,10 +725,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') # optional - 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) # optional - sage.rings.number_field + sage: P(p) # optional - sage.rings.number_field A 3-dimensional polyhedron in AA^3 defined as the convex hull of 4 vertices """ Vrep = None @@ -745,9 +752,9 @@ def base_extend(self, base_ring, backend=None, ambient_dim=None): EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra - sage: Polyhedra(ZZ,3).base_extend(QQ) + sage: Polyhedra(ZZ, 3).base_extend(QQ) Polyhedra in QQ^3 - sage: Polyhedra(ZZ,3).an_element().base_extend(QQ) + sage: Polyhedra(ZZ, 3).an_element().base_extend(QQ) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices sage: Polyhedra(QQ, 2).base_extend(ZZ) Polyhedra in QQ^2 @@ -781,9 +788,9 @@ def change_ring(self, base_ring, backend=None, ambient_dim=None): EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra - sage: Polyhedra(ZZ,3).change_ring(QQ) + sage: Polyhedra(ZZ, 3).change_ring(QQ) Polyhedra in QQ^3 - sage: Polyhedra(ZZ,3).an_element().change_ring(QQ) + sage: Polyhedra(ZZ, 3).an_element().change_ring(QQ) A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices sage: Polyhedra(RDF, 3).change_ring(QQ).backend() @@ -818,26 +825,26 @@ def _coerce_base_ring(self, other): - ``other`` -- must be either: - * another ``Polyhedron`` object + * another ``Polyhedron`` object - * `\ZZ`, `\QQ`, `RDF`, or a ring that can be coerced into them. + * `\ZZ`, `\QQ`, `RDF`, or a ring that can be coerced into them. - * a constant that can be coerced to `\ZZ`, `\QQ`, or `RDF`. + * a constant that can be coerced to `\ZZ`, `\QQ`, or `RDF`. OUTPUT: - Either `\ZZ`, `\QQ`, or `RDF`. Raises ``TypeError`` if + Either `\ZZ`, `\QQ`, or `RDF`. Raises :class:`TypeError` if ``other`` is not a suitable input. .. NOTE:: "Real" numbers in sage are not necessarily elements of - `RDF`. For example, the literal `1.0` is not. + ``RDF``. For example, the literal `1.0` is not. EXAMPLES:: - sage: triangle_QQ = Polyhedron(vertices = [[1,0],[0,1],[1,1]], base_ring=QQ).parent() - sage: triangle_RDF = Polyhedron(vertices = [[1,0],[0,1],[1,1]], base_ring=RDF).parent() + sage: triangle_QQ = Polyhedron(vertices=[[1,0],[0,1],[1,1]], base_ring=QQ).parent() + sage: triangle_RDF = Polyhedron(vertices=[[1,0],[0,1],[1,1]], base_ring=RDF).parent() sage: triangle_QQ._coerce_base_ring(QQ) Rational Field sage: triangle_QQ._coerce_base_ring(triangle_RDF) @@ -858,15 +865,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') # optional - sage.rings.number_field + sage: triangle_QQ._coerce_base_ring(K) # optional - 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()) # optional - 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') # optional - sage.rings.number_field + sage: K.gen() * polytopes.simplex(backend='field') # optional - 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 @@ -905,7 +912,7 @@ def _coerce_base_ring(self, other): def _coerce_map_from_(self, X): r""" - Return whether there is a coercion from ``X`` + Return whether there is a coercion from ``X``. INPUT: @@ -918,9 +925,9 @@ def _coerce_map_from_(self, X): EXAMPLES:: sage: from sage.geometry.polyhedron.parent import Polyhedra - sage: Polyhedra(QQ,3).has_coerce_map_from( Polyhedra(ZZ,3) ) # indirect doctest + sage: Polyhedra(QQ, 3).has_coerce_map_from(Polyhedra(ZZ, 3)) # indirect doctest True - sage: Polyhedra(ZZ,3).has_coerce_map_from( Polyhedra(QQ,3) ) + sage: Polyhedra(ZZ, 3).has_coerce_map_from(Polyhedra(QQ, 3)) False """ if not isinstance(X, Polyhedra_base): @@ -990,8 +997,10 @@ def _get_action_(self, other, op, self_is_left): sage: from sage.geometry.polyhedron.parent import Polyhedra sage: PZZ2.get_action(ZZ^2, op=operator.add) Right action by Ambient free module of rank 2 over the principal ideal domain Integer Ring on Polyhedra in ZZ^2 - with precomposition on left by Identity endomorphism of Polyhedra in ZZ^2 - with precomposition on right by Generic endomorphism of Ambient free module of rank 2 over the principal ideal domain Integer Ring + with precomposition on left by + Identity endomorphism of Polyhedra in ZZ^2 + with precomposition on right by + Generic endomorphism of Ambient free module of rank 2 over the principal ideal domain Integer Ring """ import operator @@ -1045,7 +1054,7 @@ def _make_Inequality(self, polyhedron, data): EXAMPLES:: - sage: p = Polyhedron([(1,2,3),(2/3,3/4,4/5)]) # indirect doctest + sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)]) # indirect doctest sage: next(p.inequality_generator()) An inequality (0, 0, -1) x + 3 >= 0 """ @@ -1072,7 +1081,7 @@ def _make_Equation(self, polyhedron, data): EXAMPLES:: - sage: p = Polyhedron([(1,2,3),(2/3,3/4,4/5)]) # indirect doctest + sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)]) # indirect doctest sage: next(p.equation_generator()) An equation (0, 44, -25) x - 13 == 0 """ @@ -1099,7 +1108,7 @@ def _make_Vertex(self, polyhedron, data): EXAMPLES:: - sage: p = Polyhedron([(1,2,3),(2/3,3/4,4/5)], rays=[(5/6,6/7,7/8)]) # indirect doctest + sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)], rays=[(5/6,6/7,7/8)]) # indirect doctest sage: next(p.vertex_generator()) A vertex at (1, 2, 3) """ @@ -1126,7 +1135,7 @@ def _make_Ray(self, polyhedron, data): EXAMPLES:: - sage: p = Polyhedron([(1,2,3),(2/3,3/4,4/5)], rays=[(5/6,6/7,7/8)]) # indirect doctest + sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)], rays=[(5/6,6/7,7/8)]) # indirect doctest sage: next(p.ray_generator()) A ray in the direction (140, 144, 147) """ @@ -1153,7 +1162,7 @@ def _make_Line(self, polyhedron, data): EXAMPLES:: - sage: p = Polyhedron([(1,2,3),(2/3,3/4,4/5)], lines=[(5/6,6/7,7/8)]) # indirect doctest + sage: p = Polyhedron([(1,2,3), (2/3,3/4,4/5)], lines=[(5/6,6/7,7/8)]) # indirect doctest sage: next(p.line_generator()) A line in the direction (140, 144, 147) """ @@ -1266,9 +1275,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: does_backend_handle_base_ring(QQ[sqrt(5)], 'ppl') # optional - sage.rings.number_field sage.symbolic False - sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'field') # optional - sage.rings.number_field + sage: does_backend_handle_base_ring(QQ[sqrt(5)], 'field') # optional - 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 c54b92116f3..472ab1cf8c2 100644 --- a/src/sage/geometry/polyhedron/plot.py +++ b/src/sage/geometry/polyhedron/plot.py @@ -435,11 +435,11 @@ def identity(self): EXAMPLES:: - sage: p = polytopes.icosahedron(exact=False) # optional - sage.groups + sage: p = polytopes.icosahedron(exact=False) # optional - sage.groups 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) # optional - sage.groups + sage: ppid = pproj.identity() # optional - sage.groups + sage: ppid.dimension # optional - sage.groups 3 """ return self(projection_func_identity) @@ -456,12 +456,11 @@ def stereographic(self, projection_point=None): EXAMPLES:: sage: from sage.geometry.polyhedron.plot import Projection - sage: proj = Projection(polytopes.buckyball()) #long time - sage: proj #long time + 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 # optional - sage.plot Graphics object consisting of 123 graphics primitives - sage: Projection( polytopes.twenty_four_cell() ).stereographic([2,0,0,0]) + sage: Projection(polytopes.twenty_four_cell()).stereographic([2,0,0,0]) The projection of a polyhedron into 3 dimensions """ if projection_point is None: @@ -505,24 +504,24 @@ 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 # optional - sage.symbolic + sage: into_tetra = Projection(tcube4).schlegel(tcube4.facets()[4]) # optional - sage.symbolic + sage: into_tetra.plot() # optional - 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 # optional - sage.symbolic + sage: into_tetra_far = Projection(tcube4).schlegel(tcube4.facets()[4], 4) # optional - sage.symbolic + sage: into_tetra_far.plot() # optional - sage.plot sage.symbolic Graphics3d Object A value which is too large or negative give a projection point that sees more than one facet resulting in a error:: - sage: Projection(tcube4).schlegel(tcube4.facets()[4],5) + sage: Projection(tcube4).schlegel(tcube4.facets()[4], 5) Traceback (most recent call last): ... ValueError: the chosen position is too large - sage: Projection(tcube4).schlegel(tcube4.facets()[4],-1) + sage: Projection(tcube4).schlegel(tcube4.facets()[4], -1) Traceback (most recent call last): ... ValueError: 'position' should be a positive number @@ -582,7 +581,7 @@ def coord_indices_of(self, v_list): sage: p = polytopes.hypercube(3) sage: proj = p.projection() - sage: proj.coord_indices_of([vector((1,1,1)),vector((1,-1,1))]) + sage: proj.coord_indices_of([vector((1,1,1)), vector((1,-1,1))]) [2, 3] """ return [self.coord_index_of(v) for v in v_list] @@ -638,7 +637,7 @@ def _init_from_2d(self, polyhedron): TESTS:: - sage: p = Polyhedron(vertices = [[0,0],[0,1],[1,0],[1,1]]) + sage: p = Polyhedron(vertices=[[0,0],[0,1],[1,0],[1,1]]) sage: proj = p.projection() sage: [proj.coordinates_of([i]) for i in proj.points] [[[0, 0]], [[0, 1]], [[1, 0]], [[1, 1]]] @@ -660,7 +659,7 @@ def _init_from_3d(self, polyhedron): TESTS:: - sage: p = Polyhedron(vertices = [[0,0,1],[0,1,2],[1,0,3],[1,1,5]]) + sage: p = Polyhedron(vertices=[[0,0,1],[0,1,2],[1,0,3],[1,1,5]]) sage: proj = p.projection() sage: [proj.coordinates_of([i]) for i in proj.points] [[[0, 0, 1]], [[0, 1, 2]], [[1, 0, 3]], [[1, 1, 5]]] @@ -699,7 +698,7 @@ def _init_lines_arrows(self, polyhedron): TESTS:: - sage: p = Polyhedron(ieqs = [[1, 0, 0, 1],[1,1,0,0]]) + sage: p = Polyhedron(ieqs=[[1, 0, 0, 1], [1, 1, 0, 0]]) sage: pp = p.projection() sage: pp.arrows [[0, 1], [0, 2], [0, 3], [0, 4]] @@ -711,7 +710,7 @@ def _init_lines_arrows(self, polyhedron): We check that :trac:`31802` is fixed:: - sage: x = Polyhedron(lines=[(1, 0, 0),(0, 1, 0)], rays=[(0, 0, 1)]) + sage: x = Polyhedron(lines=[(1, 0, 0), (0, 1, 0)], rays=[(0, 0, 1)]) sage: y = x.projection() sage: del y.arrows sage: y.arrows = Sequence([]) @@ -823,12 +822,12 @@ def _init_solid_3d(self, polyhedron): sage: proj.polygons [[1, 0, 2], [3, 0, 1], [2, 0, 3], [3, 1, 2]] - sage: x = Polyhedron(rays = [(-1, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)]) + sage: x = Polyhedron(rays=[(-1, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)]) sage: y = x.projection() sage: y.polygons [[5, 2, 1, 6], [2, 7, 8, 1]] - sage: cylinder = Polyhedron(vertices = [(0, 0, 0), (1, 0, 0), (0, 1, 0)], lines=[(0, 0, 1)]) + sage: cylinder = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0)], lines=[(0, 0, 1)]) sage: len(cylinder.projection().polygons) 3 """ @@ -918,8 +917,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() # optional - sage.plot + sage: points._objects # optional - sage.plot [Point set defined by 2 point(s)] """ return point2d([c + [0] for c in self.coordinates_of(self.points)], **kwds) @@ -939,8 +938,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() # optional - sage.plot + sage: outline._objects[0] # optional - sage.plot Line defined by 2 points """ if len(self.lines) == 0: @@ -957,10 +956,10 @@ 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 # optional - sage.rings.number_field - sage: hex_points._objects # optional - sage.plot # optional - sage.rings.number_field + 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 [Point set defined by 6 point(s)] """ return point2d(self.coordinates_of(self.points), **kwds) @@ -971,9 +970,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 # optional - sage.rings.number_field - sage: outline._objects[0] # optional - sage.plot # optional - sage.rings.number_field + 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 Line defined by 2 points """ wireframe = [] @@ -991,11 +990,11 @@ def render_fill_2d(self, **kwds): EXAMPLES:: - 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: 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() # optional - sage.plot + sage: filled_poly.axes_width() # optional - sage.plot 0.8 """ poly = [polygon2d(self.coordinates_of(p), **kwds) @@ -1010,8 +1009,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() # optional - sage.plot + sage: verts.bounding_box() # optional - sage.plot ((-1.0, -1.0, -1.0), (1.0, 1.0, 1.0)) """ return point3d(self.coordinates_of(self.points), **kwds) @@ -1024,8 +1023,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() # optional - sage.plot + sage: print(wire.tachyon().split('\n')[77]) # for testing # optional - sage.plot FCylinder base 1.0 1.0 -1.0 apex -1.0 1.0 -1.0 rad 0.005 texture... """ wireframe = [] @@ -1044,8 +1043,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) # optional - sage.plot + sage: type(p_solid) # optional - sage.plot """ polys = self.polygons @@ -1075,9 +1074,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()) # optional - sage.plot - sage: print(Polyhedron(ieqs=[(1,)]).projection().render_0d().description()) # optional - sage.plot + sage: P = Polyhedron(ieqs=[(1,)]) + sage: print(P.projection().render_0d().description()) # optional - sage.plot Point set defined by 1 point(s): [(0.0, 0.0)] """ if point_opts is None: @@ -1106,7 +1106,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() # optional - sage.plot Graphics object consisting of 2 graphics primitives """ plt = Graphics() @@ -1138,7 +1138,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() # optional - sage.plot Graphics object consisting of 18 graphics primitives """ plt = Graphics() @@ -1169,29 +1169,33 @@ def render_3d(self, point_opts=None, line_opts=None, polygon_opts=None): sage: p1 = Polyhedron(vertices=[[1,1,1]], rays=[[1,1,1]]) 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() + p3.projection().plot() # optional - sage.plot + 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 + ....: + 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: Polyhedron(lines=[[1,0,0], [0,1,0], [0,0,1]]).plot() # whole space # optional - sage.plot Graphics3d Object - sage: Polyhedron(vertices=[[1,1,1]], rays=[[1,0,0]], # optional - sage.plot - ....: lines=[[0,1,0],[0,0,1]]).plot() # half space + sage: Polyhedron(vertices=[[1,1,1]], rays=[[1,0,0]], # optional - sage.plot + ....: lines=[[0,1,0], [0,0,1]]).plot() # half space Graphics3d Object - sage: Polyhedron(vertices=[[1,1,1]], # optional - sage.plot - ....: lines=[[0,1,0],[0,0,1]]).plot() # R^2 in R^3 + sage: Polyhedron(lines=[[0,1,0], [0,0,1]], # optional - sage.plot + ....: vertices=[[1,1,1]]).plot() # R^2 in R^3 Graphics3d Object - sage: Polyhedron(rays=[[0,1,0],[0,0,1]], lines=[[1,0,0]]).plot() # quadrant wedge in R^2 # optional - sage.plot + sage: Polyhedron(rays=[[0,1,0], [0,0,1]], # quadrant wedge in R^2 # optional - sage.plot + ....: lines=[[1,0,0]]).plot() Graphics3d Object - sage: Polyhedron(rays=[[0,1,0]], lines=[[1,0,0]]).plot() # upper half plane in R^3 # optional - sage.plot + sage: Polyhedron(rays=[[0,1,0]], # upper half plane in R^3 # optional - sage.plot + ....: 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 # optional - sage.plot 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 # optional - sage.plot 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 # optional - sage.plot Graphics3d Object The origin is not included, if it is not in the polyhedron (:trac:`23555`):: @@ -1199,13 +1203,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() # optional - sage.plot + sage: p.bounding_box() # optional - 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) # optional - sage.plot Graphics3d Object """ pplt = None @@ -1243,28 +1247,28 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, INPUT: - - ``view`` - list (default: [0,0,1]) representing the rotation axis (see note below). - - ``angle`` - integer (default: 0) angle of rotation in degree from 0 to 360 (see note + - ``view`` -- list (default: [0,0,1]) representing the rotation axis (see note below). + - ``angle`` -- integer (default: 0) angle of rotation in degree from 0 to 360 (see note below). - - ``scale`` - integer (default: 1) specifying the scaling of the tikz picture. - - ``edge_color`` - string (default: 'blue!95!black') representing colors which tikz + - ``scale`` -- integer (default: 1) specifying the scaling of the tikz picture. + - ``edge_color`` -- string (default: 'blue!95!black') representing colors which tikz recognize. - - ``facet_color`` - string (default: 'blue!95!black') representing colors which tikz + - ``facet_color`` -- string (default: 'blue!95!black') representing colors which tikz recognize. - - ``vertex_color`` - string (default: 'green') representing colors which tikz + - ``vertex_color`` -- string (default: 'green') representing colors which tikz recognize. - - ``opacity`` - real number (default: 0.8) between 0 and 1 giving the opacity of + - ``opacity`` -- real number (default: 0.8) between 0 and 1 giving the opacity of the front facets. - - ``axis`` - Boolean (default: False) draw the axes at the origin or not. - - ``output_type`` - string (default: ``None``), valid values + - ``axis`` -- Boolean (default: False) draw the axes at the origin or not. + - ``output_type`` -- string (default: ``None``), valid values are ``None`` (deprecated), ``'LatexExpr'`` and ``'TikzPicture'``, - whether to return a LatexExpr object (which inherits from Python - str) or a ``TikzPicture`` object from module + whether to return a :class:`LatexExpr` object (which inherits from Python + :class:`str`) or a :class:`TikzPicture` object from module :mod:`sage.misc.latex_standalone` OUTPUT: - - LatexExpr object or TikzPicture object + :class:`LatexExpr` object or :class:`TikzPicture` object .. NOTE:: @@ -1296,11 +1300,12 @@ 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, output_type='TikzPicture') # optional - sage.rings.number_field - sage: type(Image1) # optional - sage.rings.number_field + 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 + ....: output_type='TikzPicture') + sage: type(Image1) # optional - sage.rings.number_field - sage: Image1 # optional - sage.rings.number_field + sage: Image1 # optional - sage.rings.number_field \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -1317,15 +1322,18 @@ 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 # 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 A second example:: sage: P2 = Polyhedron(vertices=[[1, 1], [1, 2], [2, 1]]) - 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, output_type='TikzPicture') + 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, + ....: output_type='TikzPicture') sage: Image2 \documentclass[tikz]{standalone} \begin{document} @@ -1346,7 +1354,10 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, The second example using a LatexExpr as output type:: - 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, output_type='LatexExpr') + 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, + ....: output_type='LatexExpr') sage: type(Image2) sage: print('\n'.join(Image2.splitlines()[:4])) @@ -1359,13 +1370,14 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, A third example:: - sage: P3 = Polyhedron(vertices=[[-1, -1, 2], [-1, 2, -1], [2, -1, -1]]) - sage: P3 + 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, edge_color='blue!95!black', # optional - sage.plot + sage: Image3 = P3.projection().tikz([0.5, -1, -0.1], 55, scale=3, # optional - sage.plot + ....: 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 + ....: vertex_color='yellow', axis=True, + ....: output_type='TikzPicture') + sage: Image3 # optional - sage.plot \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -1382,15 +1394,15 @@ 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 # 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 A fourth example:: - sage: P = Polyhedron(vertices=[[1,1,0,0],[1,2,0,0],[2,1,0,0],[0,0,1,0],[0,0,0,1]]) - sage: P + sage: P = Polyhedron(vertices=[[1,1,0,0], [1,2,0,0], + ....: [2,1,0,0], [0,0,1,0], [0,0,0,1]]); P A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 5 vertices sage: P.projection().tikz(output_type='TikzPicture') Traceback (most recent call last): @@ -1401,8 +1413,8 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, Make it possible to draw Schlegel diagram for 4-polytopes. :: - sage: P=Polyhedron(vertices=[[1,1,0,0],[1,2,0,0],[2,1,0,0],[0,0,1,0],[0,0,0,1]]) - sage: P + sage: P = Polyhedron(vertices=[[1,1,0,0], [1,2,0,0], + ....: [2,1,0,0], [0,0,1,0], [0,0,0,1]]); P A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 5 vertices sage: P.projection().tikz(output_type='TikzPicture') Traceback (most recent call last): @@ -1457,25 +1469,27 @@ def _tikz_2d(self, scale, edge_color, facet_color, opacity, vertex_color, axis): INPUT: - - ``scale`` - integer specifying the scaling of the tikz picture. - - ``edge_color`` - string representing colors which tikz + - ``scale`` -- integer specifying the scaling of the tikz picture. + - ``edge_color`` -- string representing colors which tikz recognize. - - ``facet_color`` - string representing colors which tikz + - ``facet_color`` -- string representing colors which tikz recognize. - - ``vertex_color`` - string representing colors which tikz + - ``vertex_color`` -- string representing colors which tikz recognize. - - ``opacity`` - real number between 0 and 1 giving the opacity of + - ``opacity`` -- real number between 0 and 1 giving the opacity of the front facets. - - ``axis`` - Boolean (default: False) draw the axes at the origin or not. + - ``axis`` -- Boolean (default: ``False``) draw the axes at the origin or not. OUTPUT: - - LatexExpr -- containing the TikZ picture. + :class:`LatexExpr` -- containing the TikZ picture. EXAMPLES:: - sage: P = Polyhedron(vertices=[[1, 1],[1, 2],[2, 1]]) - sage: Image = P.projection()._tikz_2d(scale=3, edge_color='black', facet_color='orange', opacity=0.75, vertex_color='yellow', axis=True) + sage: P = Polyhedron(vertices=[[1, 1], [1, 2], [2, 1]]) + sage: Image = P.projection()._tikz_2d(scale=3, edge_color='black', + ....: facet_color='orange', opacity=0.75, + ....: vertex_color='yellow', axis=True) sage: type(Image) sage: print('\n'.join(Image.splitlines()[:4])) @@ -1488,7 +1502,7 @@ def _tikz_2d(self, scale, edge_color, facet_color, opacity, vertex_color, axis): Scientific notation is not used in the output (:trac:`16519`):: - sage: P = Polyhedron([[2*10^-10,0],[0,1],[1,0]],base_ring=QQ) + sage: P = Polyhedron([[2*10^-10,0], [0,1], [1,0]], base_ring=QQ) sage: tikz = P.projection().tikz(output_type='TikzPicture') sage: 'e-10' in tikz.content() False @@ -1585,26 +1599,26 @@ def _tikz_2d_in_3d(self, view, angle, scale, edge_color, facet_color, INPUT: - - ``view`` - list (default: [0,0,1]) representing the rotation axis. - - ``angle`` - integer angle of rotation in degree from 0 to 360. - - ``scale`` - integer specifying the scaling of the tikz picture. - - ``edge_color`` - string representing colors which tikz + - ``view`` -- list (default: [0,0,1]) representing the rotation axis. + - ``angle`` -- integer angle of rotation in degree from 0 to 360. + - ``scale`` -- integer specifying the scaling of the tikz picture. + - ``edge_color`` -- string representing colors which tikz recognize. - - ``facet_color`` - string representing colors which tikz + - ``facet_color`` -- string representing colors which tikz recognize. - - ``vertex_color`` - string representing colors which tikz + - ``vertex_color`` -- string representing colors which tikz recognize. - - ``opacity`` - real number between 0 and 1 giving the opacity of + - ``opacity`` -- real number between 0 and 1 giving the opacity of the front facets. - - ``axis`` - Boolean draw the axes at the origin or not. + - ``axis`` -- Boolean draw the axes at the origin or not. OUTPUT: - - LatexExpr -- containing the TikZ picture. + :class:`LatexExpr` -- containing the TikZ picture. EXAMPLES:: - sage: P = Polyhedron(vertices=[[-1, -1, 2],[-1, 2, -1],[2, -1, -1]]) + sage: P = Polyhedron(vertices=[[-1, -1, 2], [-1, 2, -1], [2, -1, -1]]) sage: 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 @@ -1739,22 +1753,22 @@ def _tikz_3d_in_3d(self, view, angle, scale, edge_color, INPUT: - - ``view`` - list (default: [0,0,1]) representing the rotation axis. - - ``angle`` - integer angle of rotation in degree from 0 to 360. - - ``scale`` - integer specifying the scaling of the tikz picture. - - ``edge_color`` - string representing colors which tikz + - ``view`` -- list (default: [0,0,1]) representing the rotation axis. + - ``angle`` -- integer angle of rotation in degree from 0 to 360. + - ``scale`` -- integer specifying the scaling of the tikz picture. + - ``edge_color`` -- string representing colors which tikz recognize. - - ``facet_color`` - string representing colors which tikz + - ``facet_color`` -- string representing colors which tikz recognize. - - ``vertex_color`` - string representing colors which tikz + - ``vertex_color`` -- string representing colors which tikz recognize. - - ``opacity`` - real number between 0 and 1 giving the opacity of + - ``opacity`` -- real number between 0 and 1 giving the opacity of the front facets. - - ``axis`` - Boolean draw the axes at the origin or not. + - ``axis`` -- Boolean draw the axes at the origin or not. OUTPUT: - - LatexExpr -- containing the TikZ picture. + :class:`LatexExpr` -- containing the TikZ picture. EXAMPLES:: diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py index 08b767e54e2..9a029e565b4 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py @@ -45,7 +45,7 @@ Finally, we can compute automorphisms and identify fibrations that only differ by a lattice automorphism:: - sage: square = LatticePolytope_PPL((-1,-1),(-1,1),(1,-1),(1,1)) + 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 @@ -115,39 +115,39 @@ def LatticePolytope_PPL(*args): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: LatticePolytope_PPL((0,0),(1,0),(0,1)) + 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, Variable - sage: p = point(Linear_Expression([2,3],0)); p + sage: from ppl import point, Generator_System, C_Polyhedron, Linear_Expression # optional - pplpy + sage: p = point(Linear_Expression([2,3],0)); p # optional - pplpy point(2/1, 3/1) - sage: LatticePolytope_PPL(p) + sage: LatticePolytope_PPL(p) # optional - pplpy A 0-dimensional lattice polytope in ZZ^2 with 1 vertex - sage: P = C_Polyhedron(Generator_System(p)); P + sage: P = C_Polyhedron(Generator_System(p)); P # optional - pplpy A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point - sage: LatticePolytope_PPL(P) + sage: LatticePolytope_PPL(P) # optional - 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)) + sage: LatticePolytope_PPL((0,0), (1/2,1)) # optional - 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, Variable - sage: p = point(Linear_Expression([2,3],0), 5); p + 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 point(2/5, 3/5) - sage: LatticePolytope_PPL(p) + sage: LatticePolytope_PPL(p) # optional - pplpy Traceback (most recent call last): ... TypeError: generator is not a lattice polytope generator - sage: P = C_Polyhedron(Generator_System(p)); P + sage: P = C_Polyhedron(Generator_System(p)); P # optional - pplpy A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 point - sage: LatticePolytope_PPL(P) + sage: LatticePolytope_PPL(P) # optional - pplpy Traceback (most recent call last): ... TypeError: polyhedron has non-integral generators @@ -189,7 +189,7 @@ class LatticePolytope_PPL_class(C_Polyhedron): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: LatticePolytope_PPL((0,0),(1,0),(0,1)) + sage: LatticePolytope_PPL((0,0), (1,0), (0,1)) A 2-dimensional lattice polytope in ZZ^2 with 3 vertices """ @@ -204,7 +204,7 @@ def __repr__(self): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: P = LatticePolytope_PPL((0,0),(1,0),(0,1)) + sage: P = LatticePolytope_PPL((0,0), (1,0), (0,1)) sage: P A 2-dimensional lattice polytope in ZZ^2 with 3 vertices sage: P.__repr__() @@ -240,7 +240,7 @@ def is_bounded(self): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: LatticePolytope_PPL((0,0),(1,0),(0,1)).is_bounded() + sage: LatticePolytope_PPL((0,0), (1,0), (0,1)).is_bounded() True """ return True @@ -295,7 +295,7 @@ def bounding_box(self): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: LatticePolytope_PPL((0,0),(1,0),(0,1)).bounding_box() + sage: LatticePolytope_PPL((0,0), (1,0), (0,1)).bounding_box() ((0, 0), (1, 1)) """ box_min = [] @@ -324,7 +324,7 @@ def n_integral_points(self): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: LatticePolytope_PPL((0,0),(1,0),(0,1)).n_integral_points() + sage: LatticePolytope_PPL((0,0), (1,0), (0,1)).n_integral_points() 3 """ if self.is_empty(): @@ -349,7 +349,7 @@ def integral_points(self): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: LatticePolytope_PPL((-1,-1),(1,0),(1,1),(0,1)).integral_points() + sage: LatticePolytope_PPL((-1,-1), (1,0), (1,1), (0,1)).integral_points() ((-1, -1), (0, 0), (0, 1), (1, 0), (1, 1)) sage: simplex = LatticePolytope_PPL((1,2,3), (2,3,7), (-2,-3,-11)) @@ -385,15 +385,15 @@ def integral_points(self): sage: v = [(1,0,0), (0,1,0), (0,0,1), (0,0,-1), (0,-2,1), ....: (-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: pts1 = P.integral_points() # Sage's own code + sage: pts2 = LatticePolytope(v).points() # optional - palp sage: for p in pts1: p.set_immutable() - sage: set(pts1) == set(pts2) # optional - palp + sage: set(pts1) == set(pts2) # optional - 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 # optional - palp 23 sage: len(LatticePolytope_PPL(*v).integral_points()) # takes about 0.5 ms 23 @@ -426,7 +426,7 @@ def _integral_points_saturating(self): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: quad = LatticePolytope_PPL((-1,-1),(0,1),(1,0),(1,1)) + sage: quad = LatticePolytope_PPL((-1,-1), (0,1), (1,0), (1,1)) sage: quad._integral_points_saturating() (((-1, -1), frozenset({0, 1})), ((0, 0), frozenset()), @@ -449,7 +449,7 @@ def _integral_points_saturating(self): @cached_method def integral_points_not_interior_to_facets(self): """ - Return the integral points not interior to facets + Return the integral points not interior to facets. OUTPUT: @@ -460,7 +460,7 @@ def integral_points_not_interior_to_facets(self): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: square = LatticePolytope_PPL((-1,-1),(-1,1),(1,-1),(1,1)) + sage: square = LatticePolytope_PPL((-1,-1), (-1,1), (1,-1), (1,1)) sage: square.n_integral_points() 9 sage: square.integral_points_not_interior_to_facets() @@ -482,7 +482,8 @@ def vertices(self): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: p = LatticePolytope_PPL((-9,-6,-1,-1),(0,0,0,1),(0,0,1,0),(0,1,0,0),(1,0,0,0)) + sage: p = LatticePolytope_PPL((-9,-6,-1,-1), + ....: (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0)) sage: p.vertices() ((-9, -6, -1, -1), (0, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, 0), (1, 0, 0, 0)) sage: p.minimized_generators() @@ -502,7 +503,7 @@ def vertices(self): def vertices_saturating(self, constraint): r""" - Return the vertices saturating the constraint + Return the vertices saturating the constraint. INPUT: @@ -517,7 +518,7 @@ def vertices_saturating(self, constraint): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: p = LatticePolytope_PPL((0,0),(0,1),(1,0)) + sage: p = LatticePolytope_PPL((0,0), (0,1), (1,0)) sage: ieq = next(iter(p.constraints())); ieq x0>=0 sage: p.vertices_saturating(ieq) @@ -544,10 +545,10 @@ def is_full_dimensional(self): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: p = LatticePolytope_PPL((0,0),(0,1)) + sage: p = LatticePolytope_PPL((0,0), (0,1)) sage: p.is_full_dimensional() False - sage: q = LatticePolytope_PPL((0,0),(0,1),(1,0)) + sage: q = LatticePolytope_PPL((0,0), (0,1), (1,0)) sage: q.is_full_dimensional() True """ @@ -576,8 +577,9 @@ def fibration_generator(self, dim): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: p = LatticePolytope_PPL((-9,-6,-1,-1),(0,0,0,1),(0,0,1,0),(0,1,0,0),(1,0,0,0)) - sage: list( p.fibration_generator(2) ) + sage: p = LatticePolytope_PPL((-9,-6,-1,-1), + ....: (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0)) + sage: list(p.fibration_generator(2)) [A 2-dimensional lattice polytope in ZZ^4 with 3 vertices] """ assert self.is_full_dimensional() @@ -633,7 +635,7 @@ def pointsets_mod_automorphism(self, pointsets): INPUT: - - ``polytopes`` a tuple/list/iterable of subsets of the + - ``polytopes`` -- a tuple/list/iterable of subsets of the integral points of ``self``. OUTPUT: @@ -644,18 +646,18 @@ def pointsets_mod_automorphism(self, pointsets): EXAMPLES:: 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 # optional - sage.graphs + 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 (frozenset({(-1, -1), (1, 1)}), frozenset({(-1, 0), (1, 0)})) sage: cell24 = LatticePolytope_PPL( - ....: (1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1),(1,-1,-1,1),(0,0,-1,1), - ....: (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)) + ....: (1,0,0,0), (0,1,0,0), (0,0,1,0), (0,0,0,1), (1,-1,-1,1), (0,0,-1,1), + ....: (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: fibers = [f.vertices() for f in cell24.fibration_generator(2)] - sage: cell24.pointsets_mod_automorphism(fibers) # long time # optional - sage.groups # optional - sage.graphs + sage: cell24.pointsets_mod_automorphism(fibers) # long time # optional - sage.groups sage.graphs (frozenset({(-1, 0, 0, 0), (-1, 0, 0, 1), (0, 0, 0, -1), @@ -714,9 +716,7 @@ def contains(self, point_coordinates): - ``point_coordinates`` -- a list/tuple/iterable of rational numbers. The coordinates of the point. - OUTPUT: - - Boolean. + OUTPUT: Boolean. EXAMPLES:: @@ -739,9 +739,7 @@ def contains_origin(self): """ Test whether the polytope contains the origin - OUTPUT: - - Boolean. + OUTPUT: Boolean. EXAMPLES:: @@ -795,7 +793,7 @@ def affine_lattice_polytope(self): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: poly_4d = LatticePolytope_PPL((-9,-6,0,0),(0,1,0,0),(1,0,0,0)); poly_4d + sage: poly_4d = LatticePolytope_PPL((-9,-6,0,0), (0,1,0,0), (1,0,0,0)); poly_4d A 2-dimensional lattice polytope in ZZ^4 with 3 vertices sage: poly_4d.space_dimension() 4 @@ -825,7 +823,8 @@ def base_projection(self, fiber): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: poly = LatticePolytope_PPL((-9,-6,-1,-1),(0,0,0,1),(0,0,1,0),(0,1,0,0),(1,0,0,0)) + sage: poly = LatticePolytope_PPL((-9,-6,-1,-1), + ....: (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0)) sage: fiber = next(poly.fibration_generator(2)) sage: poly.base_projection(fiber) Finitely generated module V/W over Integer Ring with invariants (0, 0) @@ -851,7 +850,8 @@ def base_projection_matrix(self, fiber): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: poly = LatticePolytope_PPL((-9,-6,-1,-1),(0,0,0,1),(0,0,1,0),(0,1,0,0),(1,0,0,0)) + sage: poly = LatticePolytope_PPL((-9,-6,-1,-1), + ....: (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0)) sage: fiber = next(poly.fibration_generator(2)) sage: poly.base_projection_matrix(fiber) [ 0 0 -1 0] @@ -862,9 +862,9 @@ def base_projection_matrix(self, fiber): sage: proj = poly.base_projection(fiber) sage: proj_matrix = poly.base_projection_matrix(fiber) - sage: [ proj(p) for p in poly.integral_points() ] + sage: [proj(p) for p in poly.integral_points()] [(-1, -1), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 1), (1, 0)] - sage: [ proj_matrix*p for p in poly.integral_points() ] + sage: [proj_matrix*p for p in poly.integral_points()] [(1, 1), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, -1), (-1, 0)] """ return matrix(ZZ, fiber.vertices()).right_kernel_matrix() @@ -888,13 +888,14 @@ def base_rays(self, fiber, points): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: poly = LatticePolytope_PPL((-9,-6,-1,-1),(0,0,0,1),(0,0,1,0),(0,1,0,0),(1,0,0,0)) + sage: poly = LatticePolytope_PPL((-9,-6,-1,-1), + ....: (0,0,0,1), (0,0,1,0), (0,1,0,0), (1,0,0,0)) sage: fiber = next(poly.fibration_generator(2)) sage: poly.base_rays(fiber, poly.integral_points_not_interior_to_facets()) ((-1, -1), (0, 1), (1, 0)) - sage: p = LatticePolytope_PPL((1,0),(1,2),(-1,0)) - sage: f = LatticePolytope_PPL((1,0),(-1,0)) + sage: p = LatticePolytope_PPL((1,0), (1,2), (-1,0)) + sage: f = LatticePolytope_PPL((1,0), (-1,0)) sage: p.base_rays(f, p.integral_points()) ((1),) """ @@ -921,16 +922,14 @@ def has_IP_property(self): That is, the polytope is full-dimensional and the origin is a interior point not on the boundary. - OUTPUT: - - Boolean. + OUTPUT: Boolean. EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: LatticePolytope_PPL((-1,-1),(0,1),(1,0)).has_IP_property() + sage: LatticePolytope_PPL((-1,-1), (0,1), (1,0)).has_IP_property() True - sage: LatticePolytope_PPL((-1,-1),(1,1)).has_IP_property() + sage: LatticePolytope_PPL((-1,-1), (1,1)).has_IP_property() False """ origin = C_Polyhedron(point(0*Variable(self.space_dimension()))) @@ -978,22 +977,26 @@ def restricted_automorphism_group(self, vertex_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: G1234 = Z3square.restricted_automorphism_group(vertex_labels=(1,2,3,4)) # optional - sage.groups # optional - sage.graphs - sage: G1234 == PermutationGroup([[(2,3)],[(1,2),(3,4)]]) # optional - sage.groups # optional - sage.graphs + sage: G1234 = Z3square.restricted_automorphism_group( # optional - sage.groups sage.graphs + ....: vertex_labels=(1,2,3,4)) + sage: G1234 == PermutationGroup([[(2,3)], [(1,2),(3,4)]]) # optional - sage.groups sage.graphs True - sage: G = Z3square.restricted_automorphism_group() # optional - sage.groups # optional - sage.graphs - sage: G == PermutationGroup([[((1,2),(2,1))],[((0,0),(1,2)),((2,1),(3,3))],[((0,0),(3,3))]]) # optional - sage.groups # optional - sage.graphs + 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 + ....: ((2,1),(3,3))], [((0,0),(3,3))]]) True - sage: set(G.domain()) == set(Z3square.vertices()) # optional - sage.groups # optional - sage.graphs + sage: set(G.domain()) == set(Z3square.vertices()) # optional - sage.groups sage.graphs True - sage: set(map(tuple,G.orbit(Z3square.vertices()[0]))) == set([(0, 0), (1, 2), (3, 3), (2, 1)]) # optional - sage.groups # optional - sage.graphs + sage: (set(tuple(x) for x in G.orbit(Z3square.vertices()[0]))) # optional - sage.groups sage.graphs + ....: == set([(0, 0), (1, 2), (3, 3), (2, 1)]) + True sage: cell24 = LatticePolytope_PPL( - ....: (1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1),(1,-1,-1,1),(0,0,-1,1), - ....: (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 # optional - sage.graphs + ....: (1,0,0,0), (0,1,0,0), (0,0,1,0), (0,0,0,1), (1,-1,-1,1), (0,0,-1,1), + ....: (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 1152 """ if not self.is_full_dimensional(): @@ -1033,7 +1036,7 @@ def lattice_automorphism_group(self, points=None, point_labels=None): - ``point_labels`` -- A tuple of labels for the ``points`` or ``None`` (default). These will be used as labels for the do - permutation group. If ``None`` the ``points`` will be used + permutation group. If ``None``, the ``points`` will be used themselves. OUTPUT: @@ -1046,32 +1049,34 @@ 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 # optional - sage.graphs + sage: Z3square.lattice_automorphism_group() # optional - sage.groups sage.graphs 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)); G1 # optional - sage.groups # optional - sage.graphs + sage: G1 = Z3square.lattice_automorphism_group(point_labels=(1,2,3,4)) # optional - sage.groups sage.graphs + sage: G1 Permutation Group with generators [(), (2,3), (1,4), (1,4)(2,3)] - sage: G1.cardinality() # optional - sage.groups # optional - sage.graphs + sage: G1.cardinality() # optional - sage.groups sage.graphs 4 - sage: G2 = Z3square.restricted_automorphism_group(vertex_labels=(1,2,3,4)) # optional - sage.groups # optional - sage.graphs - sage: G2 == PermutationGroup([[(2,3)], [(1,2),(3,4)], [(1,4)]]) # optional - sage.groups # optional - sage.graphs + 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 True - sage: G2.cardinality() # optional - sage.groups # optional - sage.graphs + sage: G2.cardinality() # optional - sage.groups sage.graphs 8 - sage: points = Z3square.integral_points(); points + sage: points = Z3square.integral_points(); points ((0, 0), (1, 1), (1, 2), (2, 1), (2, 2), (3, 3)) - sage: Z3square.lattice_automorphism_group(points, point_labels=(1,2,3,4,5,6)) # optional - sage.groups # optional - sage.graphs + sage: Z3square.lattice_automorphism_group(points, # optional - sage.groups sage.graphs + ....: point_labels=(1,2,3,4,5,6)) Permutation Group with generators [(), (3,4), (1,6)(2,5), (1,6)(2,5)(3,4)] Point labels also work for lattice polytopes that are not full-dimensional, see :trac:`16669`:: 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 # optional - sage.graphs + 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 Permutation Group with generators [(), (1,2), (0,1), (0,1,2), (0,2,1), (0,2)] """ if not self.is_full_dimensional(): @@ -1148,17 +1153,17 @@ def _find_isomorphism_to_subreflexive_polytope(self): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: polygon = LatticePolytope_PPL((0,0,2,1),(0,1,2,0),(2,3,0,0),(2,0,0,3)) + sage: polygon = LatticePolytope_PPL((0,0,2,1), (0,1,2,0), (2,3,0,0), (2,0,0,3)) sage: polygon._find_isomorphism_to_subreflexive_polytope() (A 2-dimensional lattice polytope in ZZ^2 with 3 vertices, A 2-dimensional lattice polytope in ZZ^2 with 4 vertices, - The map A*x+b with A= - [ 1 1] - [ 0 1] - [-1 -1] - [ 1 0] - b = - (-1, 0, 3, 0)) + The map A*x+b with + A= + [ 1 1] + [ 0 1] + [-1 -1] + [ 1 0] + b = (-1, 0, 3, 0)) sage: ambient, sub, embedding = _ sage: ambient.vertices() ((0, 0), (0, 3), (3, 0)) @@ -1219,15 +1224,15 @@ def embed_in_reflexive_polytope(self, output='hom'): EXAMPLES:: sage: from sage.geometry.polyhedron.ppl_lattice_polytope import LatticePolytope_PPL - sage: polygon = LatticePolytope_PPL((0,0,2,1),(0,1,2,0),(2,3,0,0),(2,0,0,3)) + sage: polygon = LatticePolytope_PPL((0,0,2,1), (0,1,2,0), (2,3,0,0), (2,0,0,3)) sage: polygon.embed_in_reflexive_polytope() - The map A*x+b with A= - [ 1 1] - [ 0 1] - [-1 -1] - [ 1 0] - b = - (-1, 0, 3, 0) + The map A*x+b with + A= + [ 1 1] + [ 0 1] + [-1 -1] + [ 1 0] + b = (-1, 0, 3, 0) sage: polygon.embed_in_reflexive_polytope('polytope') A 2-dimensional lattice polytope in ZZ^2 with 3 vertices sage: polygon.embed_in_reflexive_polytope('points') diff --git a/src/sage/geometry/pseudolines.py b/src/sage/geometry/pseudolines.py index 37b9ee324ca..4bb8d6ac8c9 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() + sage: p.show() # optional - sage.plot **Sequence of transpositions** @@ -67,7 +67,7 @@ sage: p = PseudolineArrangement(transpositions) sage: p Arrangement of pseudolines of size 4 - sage: p.show() + sage: p.show() # optional - sage.plot Note that this ordering is not necessarily unique. @@ -75,7 +75,7 @@ **Felsner's Matrix** Felser gave an encoding of an arrangement of pseudolines that takes `n^2` bits -instead of the `n^2log(n)` bits required by the two previous encodings. +instead of the `n^2\log(n)` bits required by the two previous encodings. Instead of storing the permutation ``[3, 2, 1]`` to remember that line `l_0` crosses `l_3` then `l_2` then `l_1`, it is sufficient to remember the positions @@ -129,25 +129,27 @@ 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(), [randint(0,20*n)+random() for i in range(n)])) - sage: print(l[:5]) # not tested - [(96, 278.0130613051349), (74, 332.92512282478714), (13, 155.65820951249867), (209, 34.753946221755307), (147, 193.51376457741441)] + sage: l = sorted(zip(Subsets(20*n, n).random_element(), # optional - sage.combinat + ....: [randint(0, 20*n) + random() for i in range(n)])) + sage: print(l[:5]) # not tested # optional - sage.combinat + [(96, 278.0130613051349), (74, 332.92512282478714), (13, 155.65820951249867), + (209, 34.753946221755307), (147, 193.51376457741441)] We can now compute for each `i` the order in which line `i` meets the other lines:: - sage: permutations = [[0..i-1]+[i+1..n-1] for i in range(n)] - sage: a = lambda x : l[x][0] - sage: b = lambda x : l[x][1] - sage: for i, perm in enumerate(permutations): - ....: perm.sort(key = lambda j : (b(j)-b(i))/(a(i)-a(j))) + 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 + ....: 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) - sage: print(p) + sage: p = PseudolineArrangement(permutations) # optional - sage.combinat + sage: print(p) # optional - sage.combinat Arrangement of pseudolines of size 20 - sage: p.show(figsize=[20,8]) + sage: p.show(figsize=[20,8]) # optional - sage.combinat sage.plot Author ^^^^^^ @@ -174,12 +176,12 @@ def __init__(self, seq, encoding="auto"): INPUT: - - ``seq`` (a sequence describing the line arrangement). It can be : + - ``seq`` (a sequence describing the line arrangement). It can be: - - A list of `n` permutations of size `n-1`. - - A list of `\binom n 2` transpositions - - A Felsner matrix, given as a sequence of `n` binary vectors of - length `n-1`. + - A list of `n` permutations of size `n-1`. + - A list of `\binom n 2` transpositions + - A Felsner matrix, given as a sequence of `n` binary vectors of + length `n-1`. - ``encoding`` (information on how the data should be interpreted), and can assume any value among 'transpositions', 'permutations', 'Felsner' @@ -188,7 +190,7 @@ def __init__(self, seq, encoding="auto"): .. NOTE:: - * The pseudolines are assumed to be integers `0..(n-1)`. + * The pseudolines are assumed to be integers `0,\dots,n-1`. * For more information on the different encodings, see the :mod:`pseudolines module `'s @@ -417,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]) + sage: p.show(figsize=[7,5]) # optional - 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() + sage: p.show() # optional - 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 262c927a08a..d9ba65bbff5 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) - sage: ri_segment2 = segment2.relative_interior(); ri_segment2 + 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 Relative interior of a 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices - sage: ri_segment == ri_segment2 + sage: ri_segment == ri_segment2 # optional - 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) - sage: ri_segment2 = segment2.relative_interior(); ri_segment2 + 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 Relative interior of a 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices - sage: ri_segment != ri_segment2 + sage: ri_segment != ri_segment2 # optional - sage.rings.number_field False """ return not (self == other) diff --git a/src/sage/geometry/toric_plotter.py b/src/sage/geometry/toric_plotter.py index 07aed17663a..9a14918a2ab 100644 --- a/src/sage/geometry/toric_plotter.py +++ b/src/sage/geometry/toric_plotter.py @@ -15,7 +15,7 @@ In most cases, this module is used indirectly, e.g. :: sage: fan = toric_varieties.dP6().fan() # optional - palp - sage: fan.plot() # optional - sage.plot # optional - palp + sage: fan.plot() # optional - palp 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 - sage.plot # optional - palp + sage: fan.plot() # optional - palp 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 - sage.plot # optional - palp + sage: fan.plot() # optional - palp sage.plot Graphics object consisting of 31 graphics primitives """ @@ -135,9 +135,9 @@ class ToricPlotter(SageObject): plot, e.g. :: sage: fan = toric_varieties.dP6().fan() # optional - palp - sage: fan.plot() # optional - sage.plot # optional - palp + sage: fan.plot() # optional - palp sage.plot Graphics object consisting of 31 graphics primitives - sage: print(fan.plot()) # optional - sage.plot # optional - palp + sage: print(fan.plot()) # optional - palp sage.plot Graphics object consisting of 31 graphics primitives If you do want to create your own plotting function for some toric @@ -164,16 +164,16 @@ class ToricPlotter(SageObject): follows:: sage: from sage.geometry.toric_plotter import ToricPlotter - sage: options = dict() # use default for everything + 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: result += tp.plot_rays() # optional - palp - sage: result += tp.plot_generators() # optional - palp - sage: result += tp.plot_walls(fan(2)) # optional - palp - sage: result # 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 Graphics object consisting of 31 graphics primitives In most situations it is only necessary to include generators of rays, in @@ -389,7 +389,7 @@ def plot_generators(self): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2, [(3,4)]) - sage: tp.plot_generators() + sage: tp.plot_generators() # optional - sage.plot Graphics object consisting of 1 graphics primitive """ generators = self.generators @@ -440,7 +440,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)]) + sage: tp.plot_labels("u", [(1.5,0)]) # optional - sage.plot Graphics object consisting of 1 graphics primitive """ result = Graphics() @@ -474,7 +474,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() + sage: tp.plot_lattice() # optional - sage.plot Graphics object consisting of 1 graphics primitive """ if not self.show_lattice: @@ -518,7 +518,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)]) + sage: tp.plot_points([(1,0), (0,1)]) # optional - sage.plot Graphics object consisting of 1 graphics primitive """ return point(points, color=self.point_color, size=self.point_size, @@ -542,7 +542,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() + sage: tp.plot_ray_labels() # optional - sage.plot Graphics object consisting of 1 graphics primitive """ return self.plot_labels(self.ray_label, @@ -563,7 +563,7 @@ def plot_rays(self): sage: from sage.geometry.toric_plotter import ToricPlotter sage: tp = ToricPlotter(dict(), 2, [(3,4)]) - sage: tp.plot_rays() + sage: tp.plot_rays() # optional - sage.plot Graphics object consisting of 2 graphics primitives """ result = Graphics() @@ -605,14 +605,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]) + sage: tp.plot_walls([quadrant]) # optional - 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]) + sage: tp.plot_walls([quadrant]) # optional - sage.plot Graphics object consisting of 2 graphics primitives """ result = Graphics() @@ -702,12 +702,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() + sage: tp.plot_rays() # optional - sage.plot Traceback (most recent call last): ... AttributeError: 'ToricPlotter' object has no attribute 'rays' sage: tp.set_rays([(0,1)]) - sage: tp.plot_rays() + sage: tp.plot_rays() # optional - sage.plot Graphics object consisting of 2 graphics primitives """ d = self.dimension @@ -782,20 +782,20 @@ def color_list(color, n): EXAMPLES:: sage: from sage.geometry.toric_plotter import color_list - sage: color_list("grey", 1) + sage: color_list("grey", 1) # optional - sage.plot [RGB color (0.5019607843137255, 0.5019607843137255, 0.5019607843137255)] - sage: len(color_list("grey", 3)) + sage: len(color_list("grey", 3)) # optional - sage.plot 3 - sage: L = color_list("rainbow", 3) - sage: L + sage: L = color_list("rainbow", 3) # optional - sage.plot + sage: L # optional - sage.plot [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) + sage: color_list(L, 3) # optional - sage.plot [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) + sage: color_list(L, 4) # optional - sage.plot Traceback (most recent call last): ... ValueError: expected 4 colors, got 3! diff --git a/src/sage/geometry/triangulation/element.py b/src/sage/geometry/triangulation/element.py index b32cb952190..793b383f9dc 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) # optional - 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 # optional - 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 # optional - 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) # optional - sage.plot Graphics object consisting of 12 graphics primitives """ dim = self.point_configuration().dim() @@ -524,18 +524,17 @@ 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()) # optional - palp True Toric diagrams (the `\ZZ_5` hyperconifold):: sage: vertices=[(0, 1, 0), (0, 3, 1), (0, 2, 3), (0, 0, 2)] sage: interior=[(0, 1, 1), (0, 1, 2), (0, 2, 1), (0, 2, 2)] - sage: points = vertices+interior + sage: points = vertices + interior sage: pc = PointConfiguration(points, fine=True) sage: triangulation = pc.triangulate() - sage: fan = triangulation.fan( (-1,0,0) ) - sage: fan + sage: fan = triangulation.fan((-1,0,0)); fan Rational polyhedral fan in 3-d lattice N sage: fan.rays() N(1, 1, 0), @@ -568,13 +567,12 @@ def simplicial_complex(self): EXAMPLES:: sage: p = polytopes.cuboctahedron() - sage: sc = p.triangulate(engine='internal').simplicial_complex() - sage: sc + sage: sc = p.triangulate(engine='internal').simplicial_complex(); sc # optional - sage.graphs Simplicial complex with 12 vertices and 16 facets Any convex set is contractable, so its reduced homology groups vanish:: - sage: sc.homology() + sage: sc.homology() # optional - sage.graphs {0: 0, 1: 0, 2: 0, 3: 0} """ from sage.topology.simplicial_complex import SimplicialComplex @@ -672,20 +670,19 @@ def boundary_simplicial_complex(self): sage: p = polytopes.cuboctahedron() sage: triangulation = p.triangulate(engine='internal') - sage: bd_sc = triangulation.boundary_simplicial_complex() - sage: bd_sc + sage: bd_sc = triangulation.boundary_simplicial_complex(); bd_sc # optional - 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() + sage: bd_sc.homology() # optional - sage.graphs {0: 0, 1: 0, 2: Z} It is a subcomplex of ``self`` as a :meth:`simplicial_complex`:: - sage: sc = triangulation.simplicial_complex() - sage: all(f in sc for f in bd_sc.maximal_faces()) + sage: sc = triangulation.simplicial_complex() # optional - sage.graphs + sage: all(f in sc for f in bd_sc.maximal_faces()) # optional - sage.graphs True """ from sage.topology.simplicial_complex import SimplicialComplex @@ -742,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 + sage: C = T.polyhedral_complex(); C # optional - sage.graphs Polyhedral complex with 6 maximal cells - sage: [P.vertices_list() for P in C.maximal_cells_sorted()] + sage: [P.vertices_list() for P in C.maximal_cells_sorted()] # optional - 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]], @@ -778,26 +775,26 @@ 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 + sage: bd_C = T.boundary_polyhedral_complex(); bd_C # optional - sage.graphs Polyhedral complex with 12 maximal cells - sage: [P.vertices_list() for P in bd_C.maximal_cells_sorted()] + sage: [P.vertices_list() for P in bd_C.maximal_cells_sorted()] # optional - 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]], - [[-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]], - [[-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]]] + [[-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]], + [[-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]], + [[-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]]] It is a subcomplex of ``self`` as a :meth:`polyhedral_complex`:: - sage: C = T.polyhedral_complex() - sage: bd_C.is_subcomplex(C) + sage: C = T.polyhedral_complex() # optional - sage.graphs + sage: bd_C.is_subcomplex(C) # optional - sage.graphs True """ from sage.geometry.polyhedral_complex import PolyhedralComplex @@ -921,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() + sage: t.adjacency_graph() # optional - 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 055ecae5d60..7797636066b 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -42,8 +42,7 @@ A 2-dimensional point configuration:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) - sage: p + sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]); p A point configuration in affine 2-space over Integer Ring consisting of 5 points. The triangulations of this point configuration are assumed to be connected, not necessarily fine, not necessarily regular. @@ -51,13 +50,12 @@ .. PLOT:: :width: 300 px - p = PointConfiguration([[-1,-1],[1,1],[1,0],[0,1],[0,0]]) + p = PointConfiguration([[-1,-1], [1,1], [1,0], [0,1], [0,0]]) sphinx_plot(p.plot(axes=False)) A triangulation of it:: - sage: t = p.triangulate() # a single triangulation - sage: t + sage: t = p.triangulate(); t # a single triangulation (<1,3,4>, <2,3,4>) sage: len(t) 2 @@ -67,35 +65,34 @@ (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) # optional - sage.plot Graphics object consisting of 12 graphics primitives .. PLOT:: :width: 300 px - p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) + p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) t = p.triangulate() sphinx_plot(t.plot(axes=False)) List triangulations of it:: - sage: list( p.triangulations() ) + sage: list(p.triangulations()) [(<1,3,4>, <2,3,4>), (<0,1,3>, <0,1,4>, <0,2,3>, <0,2,4>), (<1,2,3>, <1,2,4>), (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>)] - sage: p_fine = p.restrict_to_fine_triangulations() - sage: p_fine + sage: p_fine = p.restrict_to_fine_triangulations(); p_fine A point configuration in affine 2-space over Integer Ring consisting of 5 points. The triangulations of this point configuration are assumed to be connected, fine, not necessarily regular. - sage: list( p_fine.triangulations() ) + sage: list(p_fine.triangulations()) [(<0,1,3>, <0,1,4>, <0,2,3>, <0,2,4>), (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>)] A 3-dimensional point configuration:: - sage: p = [[0,-1,-1],[0,0,1],[0,1,0], [1,-1,-1],[1,0,1],[1,1,0]] + 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 @@ -104,22 +101,25 @@ .. PLOT:: :width: 300 px - p = [[0,-1,-1],[0,0,1],[0,1,0], [1,-1,-1],[1,0,1],[1,1,0]] + p = [[0,-1,-1], [0,0,1], [0,1,0], [1,-1,-1], [1,0,1], [1,1,0]] points = PointConfiguration(p) triang = points.triangulate() sphinx_plot(triang.plot(axes=False)) The standard example of a non-regular triangulation (requires TOPCOM):: - sage: PointConfiguration.set_engine('topcom') # optional - topcom - sage: p = PointConfiguration([[-1,-5/9],[0,10/9],[1,-5/9],[-2,-10/9],[0,20/9],[2,-10/9]]) - sage: regular = p.restrict_to_regular_triangulations(True).triangulations_list() # optional - topcom - sage: nonregular = p.restrict_to_regular_triangulations(False).triangulations_list() # optional - topcom - sage: len(regular) # optional - topcom + sage: PointConfiguration.set_engine('topcom') # optional - 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) + sage: regular = p_regular.triangulations_list() # optional - topcom + sage: p_nonregular = p.restrict_to_regular_triangulations(False) + sage: nonregular = p_nonregular.triangulations_list() # optional - topcom + sage: len(regular) # optional - topcom 16 - sage: len(nonregular) # optional - topcom + sage: len(nonregular) # optional - topcom 2 - sage: nonregular[0].plot(aspect_ratio=1, axes=False) # optional - topcom # optional - sage.plot + sage: nonregular[0].plot(aspect_ratio=1, axes=False) # optional - topcom sage.plot Graphics object consisting of 25 graphics primitives sage: PointConfiguration.set_engine('internal') # to make doctests independent of TOPCOM @@ -127,8 +127,9 @@ points may lie in a hyperplane and the linear dependencies will be removed before passing the data to TOPCOM which cannot handle it:: - sage: points = [[0,0,0,1],[0,3,0,1],[3,0,0,1],[0,0,1,1],[0,3,1,1],[3,0,1,1],[1,1,2,1]] - sage: points = [ p+[1,2,3] for p in points ] + sage: points = [[0,0,0,1], [0,3,0,1], [3,0,0,1], [0,0,1,1], + ....: [0,3,1,1], [3,0,1,1], [1,1,2,1]] + sage: points = [p + [1,2,3] for p in points] sage: pc = PointConfiguration(points) sage: pc.ambient_dim() 7 @@ -138,27 +139,27 @@ (<0,1,2,6>, <0,1,3,6>, <0,2,3,6>, <1,2,4,6>, <1,3,4,6>, <2,3,5,6>, <2,4,5,6>) sage: _ in pc.triangulations() True - sage: len( pc.triangulations_list() ) + sage: len(pc.triangulations_list()) 26 AUTHORS: - - Volker Braun: initial version, 2010 +- Volker Braun: initial version, 2010 - - Josh Whitney: added functionality for computing - volumes and secondary polytopes of PointConfigurations +- Josh Whitney: added functionality for computing + volumes and secondary polytopes of PointConfigurations - - Marshall Hampton: improved documentation and doctest coverage +- Marshall Hampton: improved documentation and doctest coverage - - Volker Braun: rewrite using Parent/Element and categories. Added - a Point class. More doctests. Less zombies. +- Volker Braun: rewrite using Parent/Element and categories. Added + a Point class. More doctests. Less zombies. - - Volker Braun: Cythonized parts of it, added a C++ implementation - of the bistellar flip algorithm to enumerate all connected - triangulations. +- Volker Braun: Cythonized parts of it, added a C++ implementation + of the bistellar flip algorithm to enumerate all connected + triangulations. - - Volker Braun 2011: switched the triangulate() method to the - placing triangulation (faster). +- Volker Braun 2011: switched the triangulate() method to the + placing triangulation (faster). """ ######################################################################## @@ -237,11 +238,11 @@ class PointConfiguration(UniqueRepresentation, PointConfiguration_base): function. In other words, the shadows of the faces of a polyhedron in one higher dimension. - * ``True``: Only regular triangulations. + * ``True``: Only regular triangulations. - * ``False``: Only non-regular triangulations. + * ``False``: Only non-regular triangulations. - * ``None`` (default): Both kinds of triangulation. + * ``None`` (default): Both kinds of triangulation. - ``star`` -- either ``None`` or a point. Whether the triangulations must be star. A triangulation is star if all @@ -251,8 +252,7 @@ class PointConfiguration(UniqueRepresentation, PointConfiguration_base): EXAMPLES:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) - sage: p + sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]); p A point configuration in affine 2-space over Integer Ring consisting of 5 points. The triangulations of this point configuration are assumed to be connected, not necessarily fine, @@ -301,8 +301,8 @@ def __classcall__(cls, points, projective=False, connected=True, fine=False, reg EXAMPLES:: - sage: pc1 = PointConfiguration([[1,2],[2,3],[3,4]], connected=True) - sage: pc2 = PointConfiguration(((1,2),(2,3),(3,4)), regular=None) + sage: pc1 = PointConfiguration([[1,2], [2,3], [3,4]], connected=True) + sage: pc2 = PointConfiguration(((1,2), (2,3), (3,4)), regular=None) sage: pc1 is pc2 # indirect doctest True """ @@ -331,7 +331,8 @@ def __init__(self, points, connected, fine, regular, star, defined_affine): EXAMPLES:: - sage: p = PointConfiguration([[0,4],[2,3],[3,2],[4,0],[3,-2],[2,-3],[0,-4],[-2,-3],[-3,-2],[-4,0],[-3,2],[-2,3]]) + sage: p = PointConfiguration([[0,4], [2,3], [3,2], [4,0], [3,-2], [2,-3], + ....: [0,-4], [-2,-3], [-3,-2], [-4,0], [-3,2], [-2,3]]) sage: len(p.triangulations_list()) # long time (26s on sage.math, 2012) 16796 @@ -367,14 +368,14 @@ def set_engine(cls, engine='auto'): INPUT: - - ``engine`` -- either 'auto' (default), 'internal', or - 'topcom'. The latter two instruct this package to always use + - ``engine`` -- either ``'auto'`` (default), ``'internal'``, or + ``'topcom'``. The latter two instruct this package to always use its own triangulation algorithms or TOPCOM's algorithms, - respectively. By default ('auto'), internal routines are used. + respectively. By default (``'auto'``), internal routines are used. EXAMPLES:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) + 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>) @@ -399,11 +400,11 @@ def star_center(self): A :class:`~sage.geometry.triangulation.base.Point` if a distinguished star central point has been fixed. - ``ValueError`` exception is raised otherwise. + :class:`ValueError` exception is raised otherwise. EXAMPLES:: - sage: pc = PointConfiguration([(1,0),(-1,0),(0,1),(0,2)], star=(0,1)); pc + sage: pc = PointConfiguration([(1,0), (-1,0), (0,1), (0,2)], star=(0,1)); pc A point configuration in affine 2-space over Integer Ring consisting of 4 points. The triangulations of this point configuration are assumed to be connected, not necessarily @@ -411,8 +412,7 @@ def star_center(self): sage: pc.star_center() P(0, 1) - sage: pc_nostar = pc.restrict_to_star_triangulations(None) - sage: pc_nostar + sage: pc_nostar = pc.restrict_to_star_triangulations(None); pc_nostar A point configuration in affine 2-space over Integer Ring consisting of 4 points. The triangulations of this point configuration are assumed to be connected, not necessarily @@ -437,7 +437,8 @@ def __reduce__(self): sage: loads(p.dumps()) is p True - sage: p = PointConfiguration([[0, 1, 1], [0, 0, 1], [1, 0, 1], [1,1, 1]], projective=True) + sage: p = PointConfiguration([[0, 1, 1], [0, 0, 1], [1, 0, 1], [1,1, 1]], + ....: projective=True) sage: loads(p.dumps()) is p True """ @@ -469,7 +470,7 @@ def _element_constructor_(self, e): TESTS:: sage: p = PointConfiguration([[0, 1], [0, 0], [1, 0], [1,1]]) - sage: p._element_constructor_([ (0,1,2), (2,3,0) ]) + sage: p._element_constructor_([(0,1,2), (2,3,0)]) (<0,1,2>, <0,2,3>) """ return self.element_class(e, parent=self) @@ -491,11 +492,11 @@ def __iter__(self): sage: p = PointConfiguration([[1,1], [2,2], [3,3]]) sage: list(p) # indirect doctest [P(1, 1), P(2, 2), P(3, 3)] - sage: [ p[i] for i in range(p.n_points()) ] + sage: [p[i] for i in range(p.n_points())] [P(1, 1), P(2, 2), P(3, 3)] sage: list(p.points()) [P(1, 1), P(2, 2), P(3, 3)] - sage: [ p.point(i) for i in range(p.n_points()) ] + sage: [p.point(i) for i in range(p.n_points())] [P(1, 1), P(2, 2), P(3, 3)] """ for p in self.points(): @@ -507,15 +508,16 @@ def _repr_(self): TESTS:: - sage: p = PointConfiguration([[1,1,1],[-1,1,1],[1,-1,1],[-1,-1,1],[1,1,-1], - ....: [-1,1,-1],[1,-1,-1],[-1,-1,-1],[0,0,0]]) + sage: p = PointConfiguration([[1,1,1], [-1,1,1], [1,-1,1], [-1,-1,1], [1,1,-1], + ....: [-1,1,-1], [1,-1,-1], [-1,-1,-1], [0,0,0]]) sage: p._repr_() 'A point configuration in affine 3-space over Integer Ring consisting of 9 points. The triangulations of this point configuration are assumed to be connected, not necessarily fine, not necessarily regular.' - sage: PointConfiguration([[1, 1, 1], [-1, 1, 1], [1, -1, 1], [-1, -1, 1]], projective=True) + sage: PointConfiguration([[1, 1, 1], [-1, 1, 1], [1, -1, 1], [-1, -1, 1]], + ....: projective=True) A point configuration in projective 2-space over Integer Ring consisting of 4 points. The triangulations of this point configuration are assumed to be connected, @@ -595,7 +597,9 @@ def _TOPCOM_exec(cls, executable, input_string, verbose=True): TESTS:: sage: p = PointConfiguration([[1,1,1], [-1,1,1], [1,-1,1], [-1,-1,1], [1,1,-1]]) - sage: out = p._TOPCOM_exec('points2placingtriang', '[[0,0,0,1],[-2,0,0,1],[0,-2,0,1],[-2,-2,0,1],[0,0,-2,1]]', verbose=True) + sage: out = p._TOPCOM_exec('points2placingtriang', + ....: '[[0,0,0,1],[-2,0,0,1],[0,-2,0,1],[-2,-2,0,1],[0,0,-2,1]]', + ....: verbose=True) sage: list(out) # optional - topcom #### TOPCOM input #### # points2placingtriang @@ -688,7 +692,7 @@ def _TOPCOM_triangulations(self, verbose=True): EXAMPLES:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) + sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) sage: iter = p._TOPCOM_triangulations(verbose=True) sage: next(iter) # optional - topcom #### TOPCOM input #### @@ -734,7 +738,7 @@ def _TOPCOM_triangulate(self, verbose=True): EXAMPLES:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) + 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 (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>) @@ -776,8 +780,7 @@ def restrict_to_regular_triangulations(self, regular=True): EXAMPLES:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) - sage: p + sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]); p A point configuration in affine 2-space over Integer Ring consisting of 5 points. The triangulations of this point configuration are assumed to be connected, not necessarily @@ -821,8 +824,7 @@ def restrict_to_connected_triangulations(self, connected=True): EXAMPLES:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) - sage: p + sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]); p A point configuration in affine 2-space over Integer Ring consisting of 5 points. The triangulations of this point configuration are assumed to be connected, not necessarily @@ -859,7 +861,7 @@ def restrict_to_fine_triangulations(self, fine=True): EXAMPLES:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) + sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) sage: p A point configuration in affine 2-space over Integer Ring consisting of 5 points. The triangulations of this point @@ -900,8 +902,8 @@ def restrict_to_star_triangulations(self, star): EXAMPLES:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) - sage: len(list( p.triangulations() )) + sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) + sage: len(list(p.triangulations())) 4 sage: p_star = p.restrict_to_star_triangulations(0) sage: p_star is p.restrict_to_star_triangulations((0,0)) @@ -935,7 +937,7 @@ def triangulations(self, verbose=False): EXAMPLES:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) + sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) sage: iter = p.triangulations() sage: next(iter) (<1,3,4>, <2,3,4>) @@ -1010,7 +1012,7 @@ def triangulations_list(self, verbose=False): EXAMPLES:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1]]) + sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1]]) sage: p.triangulations_list() [(<0,1,2>, <1,2,3>), (<0,1,3>, <0,2,3>)] sage: list(map(list, p.triangulations_list())) @@ -1039,7 +1041,7 @@ def triangulate(self, verbose=False): EXAMPLES:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) + sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) sage: p.triangulate() (<1,3,4>, <2,3,4>) sage: list( p.triangulate() ) @@ -1050,7 +1052,7 @@ def triangulate(self, verbose=False): sage: p.set_engine('topcom') # optional - topcom sage: p.triangulate() # optional - topcom (<0,1,2>, <0,1,4>, <0,2,4>, <1,2,3>) - sage: list( p.triangulate() ) # optional - topcom + sage: list(p.triangulate()) # optional - topcom [(0, 1, 2), (0, 1, 4), (0, 2, 4), (1, 2, 3)] sage: p.set_engine('internal') # optional - topcom """ @@ -1077,7 +1079,7 @@ def convex_hull(self): EXAMPLES:: - sage: p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) + sage: p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) sage: p.convex_hull() A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices """ @@ -1123,21 +1125,22 @@ def restricted_automorphism_group(self): EXAMPLES:: - 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: 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 True - sage: DihedralGroup(4).is_isomorphic(G) # optional - sage.graphs, sage.groups + sage: DihedralGroup(4).is_isomorphic(G) # optional - sage.graphs sage.groups True The square with an off-center point in the middle. Note that the middle point breaks the restricted automorphism group `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 = PointConfiguration([(3/4,3/4), (1,1), (1,-1), (-1,-1), (-1,1)]) + sage: square.restricted_automorphism_group() # optional - 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(_) # optional - sage.graphs sage.groups True """ v_list = [ vector(p.projective()) for p in self ] @@ -1170,13 +1173,14 @@ def face_codimension(self, point): P(1, 0) sage: triangle.face_codimension(2) 1 - sage: triangle.face_codimension( [1,0] ) + sage: triangle.face_codimension([1,0]) 1 This also works for degenerate cases like the tip of the pyramid over a square (which saturates four inequalities):: - sage: pyramid = PointConfiguration([[1,0,0],[0,1,1],[0,1,-1],[0,-1,-1],[0,-1,1]]) + sage: pyramid = PointConfiguration([[1,0,0], [0,1,1], [0,1,-1], + ....: [0,-1,-1], [0,-1,1]]) sage: pyramid.face_codimension(0) 3 """ @@ -1245,7 +1249,7 @@ def exclude_points(self, point_idx_list): sage: q = p.exclude_points([3]) sage: list(q) [P(-1, 0), P(0, 0), P(1, -1), P(1, 1)] - sage: p.exclude_points( p.face_interior(codim=1) ).points() + sage: p.exclude_points(p.face_interior(codim=1)).points() (P(-1, 0), P(0, 0), P(1, -1), P(1, 1)) """ points = [self.point(i) for i in range(self.n_points()) @@ -1259,7 +1263,7 @@ def exclude_points(self, point_idx_list): def volume(self, simplex=None): """ - Find n! times the n-volume of a simplex of dimension n. + Find `n!` times the `n`-volume of a simplex of dimension `n`. INPUT: @@ -1268,16 +1272,16 @@ def volume(self, simplex=None): OUTPUT: - * If a simplex was passed as an argument: n!*(volume of ``simplex``). + * If a simplex was passed as an argument: `n!` * (volume of ``simplex``). - * Without argument: n!*(the total volume of the convex hull). + * Without argument: `n!` * (the total volume of the convex hull). EXAMPLES: The volume of the standard simplex should always be 1:: - sage: p = PointConfiguration([[0,0],[1,0],[0,1],[1,1]]) - sage: p.volume( [0,1,2] ) + sage: p = PointConfiguration([[0,0], [1,0], [0,1], [1,1]]) + sage: p.volume([0,1,2]) 1 sage: simplex = p.triangulate()[0] # first simplex of triangulation sage: p.volume(simplex) @@ -1291,9 +1295,9 @@ def volume(self, simplex=None): .. note:: - We return n!*(metric volume of the simplex) to ensure that + We return `n!` * (metric volume of the simplex) to ensure that the volume is an integer. Essentially, this normalizes - things so that the volume of the standard n-simplex is 1. + things so that the volume of the standard `n`-simplex is 1. See [GKZ1994]_ page 182. """ if (simplex is None): @@ -1324,7 +1328,7 @@ def secondary_polytope(self): EXAMPLES:: - sage: p = PointConfiguration([[0,0],[1,0],[2,1],[1,2],[0,1]]) + sage: p = PointConfiguration([[0,0], [1,0], [2,1], [1,2], [0,1]]) sage: poly = p.secondary_polytope() sage: poly.vertices_matrix() [1 1 3 3 5] @@ -1437,7 +1441,7 @@ def circuits(self): EXAMPLES:: - sage: p = PointConfiguration([(0,0),(+1,0),(-1,0),(0,+1),(0,-1)]) + sage: p = PointConfiguration([(0,0), (+1,0), (-1,0), (0,+1), (0,-1)]) sage: sorted(p.circuits()) [((0,), (1, 2), (3, 4)), ((0,), (3, 4), (1, 2)), ((1, 2), (0,), (3, 4))] @@ -1452,7 +1456,7 @@ def circuits(self): ....: [ 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0] ....: ]) sage: p = PointConfiguration(U.columns()) - sage: len( p.circuits() ) # long time + sage: len(p.circuits()) # long time 218 """ try: @@ -1492,7 +1496,8 @@ def positive_circuits(self, *negative): EXAMPLES:: - sage: p = PointConfiguration([(1,0,0),(0,1,0),(0,0,1),(-2,0,-1),(-2,-1,0),(-3,-1,-1),(1,1,1),(-1,0,0),(0,0,0)]) + sage: p = PointConfiguration([(1,0,0), (0,1,0), (0,0,1), (-2,0,-1), (-2,-1,0), + ....: (-3,-1,-1), (1,1,1), (-1,0,0), (0,0,0)]) sage: sorted(p.positive_circuits(8)) [(0, 1, 2, 5), (0, 1, 4), (0, 2, 3), (0, 3, 4, 6), (0, 5, 6), (0, 7)] sage: p.positive_circuits(0,5,6) @@ -1525,9 +1530,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) # optional - sage.plot Graphics object consisting of 11 graphics primitives - sage: Tneg.plot(axes=False) # optional - sage.plot + sage: Tneg.plot(axes=False) # optional - sage.plot Graphics object consisting of 11 graphics primitives The 3d analog:: @@ -1542,7 +1547,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) # optional - sage.plot Graphics3d Object """ flips = [] @@ -1565,13 +1570,13 @@ def lexicographic_triangulation(self): EXAMPLES:: - sage: p = PointConfiguration([(0,0),(+1,0),(-1,0),(0,+1),(0,-1)]) + sage: p = PointConfiguration([(0,0), (+1,0), (-1,0), (0,+1), (0,-1)]) sage: p.lexicographic_triangulation() (<1,3,4>, <2,3,4>) TESTS:: - sage: U=matrix([ + sage: U = matrix([ ....: [ 0, 0, 0, 0, 0, 2, 4,-1, 1, 1, 0, 0, 1, 0], ....: [ 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0], ....: [ 0, 2, 0, 0, 0, 0,-1, 0, 1, 0, 1, 0, 0, 1], @@ -1670,7 +1675,7 @@ def distance_affine(self, x, y): EXAMPLES:: sage: pc = PointConfiguration([(0,0),(1,0),(2,1),(1,2),(0,1)]) - sage: [ pc.distance_affine(pc.point(0), p) for p in pc.points() ] + sage: [pc.distance_affine(pc.point(0), p) for p in pc.points()] [0, 1, 5, 5, 1] """ self._assert_is_affine() @@ -1705,8 +1710,8 @@ def distance_FS(self, x, y): EXAMPLES:: - sage: pc = PointConfiguration([(0,0),(1,0),(2,1),(1,2),(0,1)]) - sage: [ pc.distance_FS(pc.point(0), p) for p in pc.points() ] + sage: pc = PointConfiguration([(0,0), (1,0), (2,1), (1,2), (0,1)]) + sage: [pc.distance_FS(pc.point(0), p) for p in pc.points()] [0, 1/2, 5/6, 5/6, 1/2] """ x2 = y2 = xy = 0 @@ -1735,12 +1740,13 @@ def distance(self, x, y): EXAMPLES:: - sage: pc = PointConfiguration([(0,0),(1,0),(2,1),(1,2),(0,1)]) - sage: [ pc.distance(pc.point(0), p) for p in pc.points() ] + sage: pc = PointConfiguration([(0,0), (1,0), (2,1), (1,2), (0,1)]) + sage: [pc.distance(pc.point(0), p) for p in pc.points()] [0, 1, 5, 5, 1] - sage: pc = PointConfiguration([(0,0,1),(1,0,1),(2,1,1),(1,2,1),(0,1,1)], projective=True) - sage: [ pc.distance(pc.point(0), p) for p in pc.points() ] + sage: pc = PointConfiguration([(0,0,1), (1,0,1), (2,1,1), (1,2,1), (0,1,1)], + ....: projective=True) + sage: [pc.distance(pc.point(0), p) for p in pc.points()] [0, 1/2, 5/6, 5/6, 1/2] """ if self.is_affine(): @@ -1767,8 +1773,8 @@ def farthest_point(self, points, among=None): EXAMPLES:: - sage: pc = PointConfiguration([(0,0),(1,0),(1,1),(0,1)]) - sage: pc.farthest_point([ pc.point(0) ]) + sage: pc = PointConfiguration([(0,0), (1,0), (1,1), (0,1)]) + sage: pc.farthest_point([pc.point(0)]) P(1, 1) """ if len(points)==0: @@ -1822,7 +1828,7 @@ def contained_simplex(self, large=True, initial_point=None, point_order=None): EXAMPLES:: - sage: pc = PointConfiguration([(0,0),(1,0),(2,1),(1,1),(0,1)]) + sage: pc = PointConfiguration([(0,0), (1,0), (2,1), (1,1), (0,1)]) sage: pc.contained_simplex() (P(0, 1), P(2, 1), P(1, 0)) sage: pc.contained_simplex(large=False) @@ -1830,23 +1836,23 @@ def contained_simplex(self, large=True, initial_point=None, point_order=None): sage: pc.contained_simplex(initial_point=pc.point(2)) (P(2, 1), P(0, 0), P(1, 0)) - sage: pc = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) + sage: pc = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) sage: pc.contained_simplex() (P(-1, -1), P(1, 1), P(0, 1)) - sage: pc.contained_simplex(point_order = [pc[1],pc[3],pc[4],pc[2],pc[0]]) + sage: pc.contained_simplex(point_order=[pc[1], pc[3], pc[4], pc[2], pc[0]]) (P(0, 1), P(1, 1), P(-1, -1)) Lower-dimensional example:: - sage: pc.contained_simplex(point_order = [pc[0],pc[3],pc[4]]) + sage: pc.contained_simplex(point_order=[pc[0], pc[3], pc[4]]) (P(0, 0), P(1, 1)) TESTS:: - sage: pc = PointConfiguration([[0,0],[0,1],[1,0]]) + sage: pc = PointConfiguration([[0,0], [0,1], [1,0]]) sage: pc.contained_simplex() (P(1, 0), P(0, 1), P(0, 0)) - sage: pc = PointConfiguration([[0,0],[0,1]]) + sage: pc = PointConfiguration([[0,0], [0,1]]) sage: pc.contained_simplex() (P(0, 1), P(0, 0)) sage: pc = PointConfiguration([[0,0]]) @@ -1907,14 +1913,14 @@ def placing_triangulation(self, point_order=None): EXAMPLES:: - sage: pc = PointConfiguration([(0,0),(1,0),(2,1),(1,2),(0,1)]) + sage: pc = PointConfiguration([(0,0), (1,0), (2,1), (1,2), (0,1)]) sage: pc.placing_triangulation() (<0,1,2>, <0,2,4>, <2,3,4>) sage: pc.placing_triangulation(point_order=(3,2,1,4,0)) (<0,1,4>, <1,2,3>, <1,3,4>) - sage: pc.placing_triangulation(point_order=[pc[1],pc[3],pc[4],pc[0]]) + sage: pc.placing_triangulation(point_order=[pc[1], pc[3], pc[4], pc[0]]) (<0,1,4>, <1,3,4>) - sage: U=matrix([ + sage: U = matrix([ ....: [ 0, 0, 0, 0, 0, 2, 4,-1, 1, 1, 0, 0, 1, 0], ....: [ 0, 0, 0, 1, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0], ....: [ 0, 2, 0, 0, 0, 0,-1, 0, 1, 0, 1, 0, 0, 1], @@ -1931,7 +1937,7 @@ def placing_triangulation(self, point_order=None): <3,4,6,7,11,12>, <3,4,7,11,12,13>, <3,6,7,11,12,13>, <4,6,7,11,12,13>) sage: sum(p.volume(t) for t in triangulation) 42 - sage: p0 = PointConfiguration([(0,0),(+1,0),(-1,0),(0,+1),(0,-1)]) + sage: p0 = PointConfiguration([(0,0), (+1,0), (-1,0), (0,+1), (0,-1)]) sage: p0.pushing_triangulation(point_order=[1,2,0,3,4]) (<1,2,3>, <1,2,4>) sage: p0.pushing_triangulation(point_order=[0,1,2,3,4]) @@ -1939,7 +1945,7 @@ def placing_triangulation(self, point_order=None): The same triangulation with renumbered points 0->4, 1->0, etc:: - sage: p1 = PointConfiguration([(+1,0),(-1,0),(0,+1),(0,-1),(0,0)]) + sage: p1 = PointConfiguration([(+1,0), (-1,0), (0,+1), (0,-1), (0,0)]) sage: p1.pushing_triangulation(point_order=[4,0,1,2,3]) (<0,2,4>, <0,3,4>, <1,2,4>, <1,3,4>) """ @@ -2049,7 +2055,7 @@ def Gale_transform(self, points=None): EXAMPLES:: - sage: pc = PointConfiguration([(0,0),(1,0),(2,1),(1,1),(0,1)]) + sage: pc = PointConfiguration([(0,0), (1,0), (2,1), (1,1), (0,1)]) sage: pc.Gale_transform() [ 1 -1 0 1 -1] [ 0 0 1 -2 1] @@ -2078,14 +2084,14 @@ 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 = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) + sage: p.plot(axes=False) # optional - sage.plot Graphics object consisting of 5 graphics primitives .. PLOT:: :width: 300 px - p = PointConfiguration([[0,0],[0,1],[1,0],[1,1],[-1,-1]]) + p = PointConfiguration([[0,0], [0,1], [1,0], [1,1], [-1,-1]]) sphinx_plot(p.plot(axes=False)) """ return self.element_class([], parent=self, check=False).plot(**kwds) From cfb0331cf45386aa09ab202ddd816e9a5a8fe169 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 30 Apr 2023 16:12:31 -0700 Subject: [PATCH 2/5] sage.geometry: Add some # optional, reformat doctests (fixup) --- src/sage/geometry/polyhedron/base7.py | 4 +- src/sage/geometry/polyhedron/base_QQ.py | 118 +++++++++--------- src/sage/geometry/polyhedron/library.py | 2 +- .../polyhedron/ppl_lattice_polytope.py | 2 +- .../triangulation/point_configuration.py | 4 +- 5 files changed, 64 insertions(+), 66 deletions(-) diff --git a/src/sage/geometry/polyhedron/base7.py b/src/sage/geometry/polyhedron/base7.py index 2f1fb4cf45e..ce632e1655d 100644 --- a/src/sage/geometry/polyhedron/base7.py +++ b/src/sage/geometry/polyhedron/base7.py @@ -583,8 +583,8 @@ def volume(self, measure='ambient', engine='auto', **kwds): sage: Dinexact = polytopes.dodecahedron(exact=False) # optional - sage.groups sage: F2 = Dinexact.faces(2)[2].as_polyhedron() - sage: w = F2.volume(measure='induced', engine='internal') # abs tol 1e-9 # optional - sage.groups - sage: RDF(w) + sage: w = F2.volume(measure='induced', engine='internal') # optional - sage.groups + sage: RDF(w) # abs tol 1e-9 1.5340627082974878 sage: all(polytopes.simplex(d).volume(measure='induced') # optional - sage.rings.number_field sage.symbolic diff --git a/src/sage/geometry/polyhedron/base_QQ.py b/src/sage/geometry/polyhedron/base_QQ.py index 51fd9742159..d279aa5ea7f 100644 --- a/src/sage/geometry/polyhedron/base_QQ.py +++ b/src/sage/geometry/polyhedron/base_QQ.py @@ -97,13 +97,13 @@ def integral_points_count(self, verbose=False, use_Hrepresentation=False, INPUT: - - ``verbose`` (boolean; ``False`` by default) -- whether to display + - ``verbose`` -- (boolean; ``False`` by default) whether to display verbose output. - - ``use_Hrepresentation`` - (boolean; ``False`` by default) -- whether + - ``use_Hrepresentation`` -- (boolean; ``False`` by default) -- whether to send the H or V representation to LattE - - ``preprocess`` - (boolean; ``True`` by default) -- whether, if the integral hull + - ``preprocess`` -- (boolean; ``True`` by default) whether, if the integral hull is known to lie in a coordinate hyperplane, to tighten bounds to reduce dimension .. SEEALSO:: @@ -243,12 +243,12 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, is computed using LattE Integrale (optional) * ``'latte'``; use LattE integrale program (optional) * ``'normaliz'``; use Normaliz program (optional package pynormaliz). - The backend of ``self`` must be set to 'normaliz'. + The backend of ``self`` must be set to ``'normaliz'``. - - ``variable`` -- string (default: 't'); The variable in which the - Ehrhart polynomial should be expressed. + - ``variable`` -- string (default: ``'t'``); The variable in which the + Ehrhart polynomial should be expressed. - - When the ``engine`` is 'latte', the additional input values are: + - When the ``engine`` is ``'latte'``, the additional input values are: * ``verbose`` - boolean (default: ``False``); If ``True``, print the whole output of the LattE command. @@ -259,9 +259,9 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, * ``dual`` - boolean; triangulate and signed-decompose in the dual space - * ``irrational_primal`` - boolean; triangulate in the dual space, + * ``irrational_primal`` -- boolean; triangulate in the dual space, signed-decompose in the primal space using irrationalization. - * ``irrational_all_primal`` - boolean; triangulate and signed-decompose + * ``irrational_all_primal`` -- boolean; triangulate and signed-decompose in the primal space using irrationalization. * ``maxdet`` -- integer; decompose down to an index (determinant) of ``maxdet`` instead of index 1 (unimodular cones). @@ -270,8 +270,8 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, * ``compute_vertex_cones`` -- string; either 'cdd' or 'lrs' or '4ti2' * ``smith_form`` -- string; either 'ilio' or 'lidia' * ``dualization`` -- string; either 'cdd' or '4ti2' - * ``triangulation`` - string; 'cddlib', '4ti2' or 'topcom' - * ``triangulation_max_height`` - integer; use a uniform distribution + * ``triangulation`` -- string; 'cddlib', '4ti2' or 'topcom' + * ``triangulation_max_height`` -- integer; use a uniform distribution of height from 1 to this number OUTPUT: @@ -287,7 +287,7 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, To start, we find the Ehrhart polynomial of a three-dimensional ``simplex``, first using ``engine='latte'``. Leaving the engine - unspecified sets the ``engine`` to 'latte' by default:: + unspecified sets the ``engine`` to ``'latte'`` by default:: sage: simplex = Polyhedron(vertices=[(0,0,0),(3,3,3),(-3,2,1),(1,-1,-2)]) sage: simplex = simplex.change_ring(QQ) @@ -408,7 +408,7 @@ def ehrhart_quasipolynomial(self, variable='t', engine=None, verbose=False, INPUT: - - ``variable`` -- string (default: 't'); The variable in which the + - ``variable`` -- string (default: ``'t'``); The variable in which the Ehrhart polynomial should be expressed. - ``engine`` -- string; The backend to use. Allowed values are: @@ -429,21 +429,21 @@ def ehrhart_quasipolynomial(self, variable='t', engine=None, verbose=False, consult `the LattE documentation `__: - * ``dual`` - boolean; triangulate and signed-decompose in the dual + * ``dual`` -- boolean; triangulate and signed-decompose in the dual space - * ``irrational_primal`` - boolean; triangulate in the dual space, + * ``irrational_primal`` -- boolean; triangulate in the dual space, signed-decompose in the primal space using irrationalization. - * ``irrational_all_primal`` - boolean; triangulate and signed-decompose + * ``irrational_all_primal`` -- boolean; triangulate and signed-decompose in the primal space using irrationalization. * ``maxdet`` -- integer; decompose down to an index (determinant) of ``maxdet`` instead of index 1 (unimodular cones). * ``no_decomposition`` -- boolean; do not signed-decompose simplicial cones. - * ``compute_vertex_cones`` -- string; either 'cdd' or 'lrs' or '4ti2' - * ``smith_form`` -- string; either 'ilio' or 'lidia' - * ``dualization`` -- string; either 'cdd' or '4ti2' - * ``triangulation`` - string; 'cddlib', '4ti2' or 'topcom' - * ``triangulation_max_height`` - integer; use a uniform distribution of + * ``compute_vertex_cones`` -- string; either ``'cdd'`` or ``'lrs'`` or ``'4ti2'`` + * ``smith_form`` -- string; either ``'ilio'`` or ``'lidia'`` + * ``dualization`` -- string; either ``'cdd'`` or ``'4ti2'`` + * ``triangulation`` - string; ``'cddlib'``, ``'4ti2'`` or ``'topcom'`` + * ``triangulation_max_height`` -- integer; use a uniform distribution of height from 1 to this number OUTPUT: @@ -471,8 +471,7 @@ def ehrhart_quasipolynomial(self, variable='t', engine=None, verbose=False, backend of the polytope to 'normaliz':: sage: line_seg = Polyhedron(vertices=[[0], [1/2]], # optional - pynormaliz - ....: backend='normaliz') - sage: line_seg # optional - pynormaliz + ....: backend='normaliz'); line_seg A 1-dimensional polyhedron in QQ^1 defined as the convex hull of 2 vertices sage: line_seg.ehrhart_quasipolynomial() # optional - pynormaliz (1/2*t + 1, 1/2*t + 1/2) @@ -527,7 +526,7 @@ def ehrhart_quasipolynomial(self, variable='t', engine=None, verbose=False, polynomial is returned:: sage: simplex = Polyhedron(vertices=[(0,0,0), (3,3,3), # optional - pynormaliz - ....: (-3,2,1),(1,-1,-2)], + ....: (-3,2,1), (1,-1,-2)], ....: backend='normaliz') sage: simplex = simplex.change_ring(QQ) # optional - pynormaliz sage: poly = simplex.ehrhart_quasipolynomial( # optional - pynormaliz @@ -589,7 +588,7 @@ def _ehrhart_quasipolynomial_normaliz(self, variable='t'): INPUT: - - ``variable`` -- string (default: 't'); The variable in which the + - ``variable`` -- string (default: ``'t'``); The variable in which the Ehrhart polynomial is expressed. OUTPUT: @@ -652,20 +651,20 @@ def _ehrhart_polynomial_latte(self, verbose=False, dual=None, INPUT: - - ``verbose`` - boolean (default: ``False``); if ``True``, print the + - ``verbose`` -- boolean (default: ``False``); if ``True``, print the whole output of the LattE command. The following options are passed to the LattE command, for details you should consult `the LattE documentation `__: - - ``dual`` - boolean; triangulate and signed-decompose in the dual + - ``dual`` -- boolean; triangulate and signed-decompose in the dual space - - ``irrational_primal`` - boolean; triangulate in the dual space, + - ``irrational_primal`` -- boolean; triangulate in the dual space, signed-decompose in the primal space using irrationalization. - - ``irrational_all_primal`` - boolean; triangulate and signed-decompose + - ``irrational_all_primal`` -- boolean; triangulate and signed-decompose in the primal space using irrationalization. - ``maxdet`` -- integer; decompose down to an index (determinant) of @@ -673,15 +672,15 @@ def _ehrhart_polynomial_latte(self, verbose=False, dual=None, - ``no_decomposition`` -- boolean; do not signed-decompose simplicial cones. - - ``compute_vertex_cones`` -- string; either 'cdd' or 'lrs' or '4ti2' + - ``compute_vertex_cones`` -- string; either ``'cdd'`` or ``'lrs'`` or ``'4ti2'`` - - ``smith_form`` -- string; either 'ilio' or 'lidia' + - ``smith_form`` -- string; either ``'ilio'`` or ``'lidia'`` - - ``dualization`` -- string; either 'cdd' or '4ti2' + - ``dualization`` -- string; either ``'cdd'`` or ``'4ti2'`` - - ``triangulation`` - string; 'cddlib', '4ti2' or 'topcom' + - ``triangulation`` -- string; ``'cddlib'``, ``'4ti2'`` or ``'topcom'`` - - ``triangulation_max_height`` - integer; use a uniform distribution of + - ``triangulation_max_height`` -- integer; use a uniform distribution of height from 1 to this number .. NOTE:: @@ -853,7 +852,7 @@ def fixed_subpolytope(self, vertex_permutation): You can obtain non-trivial examples:: - sage: G = AG([(0,1),(2,3),(4,5),(6,7)]) + sage: G = AG([(0,1),(2,3),(4,5),(6,7)]) # optional - pynormaliz sage: fsp = Cube.fixed_subpolytope(G); fsp # optional - pynormaliz A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices sage: fsp.vertices() # optional - pynormaliz @@ -874,7 +873,7 @@ def fixed_subpolytope(self, vertex_permutation): sage: len(G) # optional - pynormaliz 2 sage: fixed_set = P.fixed_subpolytope(G.gens()[0]) # optional - pynormaliz - sage: fixed_set + sage: fixed_set # optional - pynormaliz A 0-dimensional polyhedron in QQ^1 defined as the convex hull of 1 vertex sage: fixed_set.vertices_list() # optional - pynormaliz [[1/4]] @@ -922,7 +921,7 @@ def fixed_subpolytopes(self, conj_class_reps): INPUT: - ``conj_class_reps`` -- a list of representatives of the conjugacy - classes of the subgroup of the ``restricted_automorphism_group`` of + classes of the subgroup of the :meth:`restricted_automorphism_group` of the polytope. Each element is written as a permutation of the vertices of the polytope. @@ -988,24 +987,24 @@ def Hstar_function(self, acting_group=None, output=None): - ``acting_group`` -- (default=None) a permgroup object. A subgroup of the polytope's ``restricted_automorphism_group``. If ``None``, it is set to the full ``restricted_automorphism_group`` of the - polytope. The acting group should always use output='permutation'. + polytope. The acting group should always use ``output='permutation'``. - ``output`` -- string. an output option. The allowed values are: - * ``None`` (default): returns the rational function `H^*(t)`. `H^*` - is a rational function in `t` with coefficients in the ring of - class functions. - * ``'e_series_list'``: Returns a list of the ehrhart_series for the - fixed_subpolytopes of each conjugacy class representative. - * ``'determinant_vec'``: Returns a list of the determinants - of `Id-\rho*t` for each conjugacy class representative. - * ``'Hstar_as_lin_comb'``: Returns a vector of the coefficients - of the irreducible representations in the expression of `H^*`. - * ``'prod_det_es'``: Returns a vector of the product of - determinants and the Ehrhart series. - * ``'complete'``: Returns a list with Hstar, - Hstar_as_lin_comb, character table of the acting group, and - whether Hstar is effective. + * ``None`` (default): returns the rational function `H^*(t)`. `H^*` + is a rational function in `t` with coefficients in the ring of + class functions. + * ``'e_series_list'``: Returns a list of the ehrhart_series for the + fixed_subpolytopes of each conjugacy class representative. + * ``'determinant_vec'``: Returns a list of the determinants + of `Id-\rho*t` for each conjugacy class representative. + * ``'Hstar_as_lin_comb'``: Returns a vector of the coefficients + of the irreducible representations in the expression of `H^*`. + * ``'prod_det_es'``: Returns a vector of the product of + determinants and the Ehrhart series. + * ``'complete'``: Returns a list with ``Hstar``, + ``Hstar_as_lin_comb``, character table of the acting group, and + whether ``Hstar`` is effective. OUTPUT: @@ -1018,7 +1017,7 @@ class functions. EXAMPLES: The `H^*`-polynomial of the standard (`d-1`)-dimensional simplex - `S = conv(e_1, \dots, e_d)` under its ``restricted_automorphism_group`` + `S = conv(e_1, \dots, e_d)` under its :meth:`restricted_automorphism_group` is equal to 1 = `\chi_{trivial}` (Prop 6.1 [Stap2011]_). Here is the computation for the 3-dimensional standard simplex:: @@ -1075,9 +1074,8 @@ 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, # optional - pynormaliz - ....: output='Hstar_as_lin_comb') - sage: lin + sage: lin = P._Hstar_function_normaliz( # optional - pynormaliz + ....: G, output='Hstar_as_lin_comb'); lin ((t^4 + 3*t^3 + 8*t^2 + 3*t + 1)/(t + 1), (3*t^3 + 2*t^2 + 3*t)/(t + 1)) """ @@ -1142,7 +1140,7 @@ def is_effective(self, Hstar, Hstar_as_lin_comb): Test for the effectiveness of the ``Hstar`` series of this polytope. The ``Hstar`` series of the polytope is determined by the action of a - subgroup of the polytope's ``restricted_automorphism_group``. The + subgroup of the polytope's :meth:`restricted_automorphism_group`. The ``Hstar`` series is effective if it is a polynomial in `t` and the coefficient of each `t^i` is an effective character in the ring of class functions of the acting group. A character `\rho` is effective if @@ -1183,7 +1181,7 @@ class functions of the acting group. A character `\rho` is effective if sage: Hstar = p3.Hstar_function(S3) # optional - pynormaliz sage: Hlin = p3.Hstar_function(S3, # optional - pynormaliz ....: output='Hstar_as_lin_comb')] - sage: p3.is_effective(Hstar,Hlin) # optional - pynormaliz + sage: p3.is_effective(Hstar, Hlin) # optional - pynormaliz True If the `H^*`-series is not polynomial, then it is not effective:: @@ -1217,7 +1215,7 @@ def _is_effective_normaliz(self, Hstar, Hstar_as_lin_comb): Test for the effectiveness of the ``Hstar`` series of this polytope. The ``Hstar`` series of the polytope is determined by the action of a - subgroup of the polytope's ``restricted_automorphism_group``. The + subgroup of the polytope's :meth:`restricted_automorphism_group`. The ``Hstar`` series is effective if it is a polynomial in `t` and the coefficient of each `t^i` is an effective character in the ring of class functions of the acting group. A character `\rho` is effective if @@ -1243,7 +1241,7 @@ class functions of the acting group. A character `\rho` is effective if sage: p1 = Polyhedron(vertices=[[0], [1/2]]) sage: p2 = Polyhedron(vertices=[[0], [1/2]], # optional - pynormaliz ....: backend='normaliz') - sage: Hstar = p2.Hstar_function() + sage: Hstar = p2.Hstar_function() # optional - pynormaliz sage: Hstarlin = p2.Hstar_function(output='Hstar_as_lin_comb')] # optional - pynormaliz sage: p1._is_effective_normaliz(Hstar, Hstarlin) # optional - pynormaliz Traceback (most recent call last): diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py index 5a39dcab511..7664b0eced7 100644 --- a/src/sage/geometry/polyhedron/library.py +++ b/src/sage/geometry/polyhedron/library.py @@ -2649,7 +2649,7 @@ 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 + sage: perm_b3 # long time # optional - 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 diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py index 9a029e565b4..1d4950c482b 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py @@ -987,7 +987,7 @@ def restricted_automorphism_group(self, vertex_labels=None): True sage: set(G.domain()) == set(Z3square.vertices()) # optional - sage.groups sage.graphs 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])) # optional - sage.groups sage.graphs ....: == set([(0, 0), (1, 2), (3, 3), (2, 1)]) True diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index 7797636066b..4f1bbde16d7 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -111,9 +111,9 @@ sage: PointConfiguration.set_engine('topcom') # optional - 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) + 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) + sage: p_nonregular = p.restrict_to_regular_triangulations(False) # optional - topcom sage: nonregular = p_nonregular.triangulations_list() # optional - topcom sage: len(regular) # optional - topcom 16 From 28fcec5f6766a8b8502628b4d5f6a2a5095d3703 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 13 May 2023 11:49:55 -0700 Subject: [PATCH 3/5] sage.geometry: Fix # optional, reformat doctests --- .../geometry/hyperplane_arrangement/plot.py | 8 +- .../polyhedron/ppl_lattice_polytope.py | 3 +- .../parametrized_surface3d.py | 136 +++++++++++------- 3 files changed, 89 insertions(+), 58 deletions(-) diff --git a/src/sage/geometry/hyperplane_arrangement/plot.py b/src/sage/geometry/hyperplane_arrangement/plot.py index 016f2c9b409..d2c62f2d547 100644 --- a/src/sage/geometry/hyperplane_arrangement/plot.py +++ b/src/sage/geometry/hyperplane_arrangement/plot.py @@ -496,12 +496,12 @@ def legend_3d(hyperplane_arrangement, hyperplane_colors, length): sage: legend_3d(c, list(colors.values())[:12], length='long') # optional - sage.combinat sage.plot Graphics object consisting of 12 graphics primitives - sage: legend_3d(c, list(colors.values())[:12], length='short') # optional - sage.plot + sage: legend_3d(c, list(colors.values())[:12], length='short') # optional - sage.combinat sage.plot Graphics object consisting of 12 graphics primitives - sage: p = legend_3d(c, list(colors.values())[:12], length='short') # optional - sage.plot - sage: p.set_legend_options(ncol=4) # optional - sage.plot - sage: type(p) # optional - sage.plot + 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 """ if hyperplane_arrangement.dimension() != 3: diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py index 1d4950c482b..6cd4cd457f0 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py @@ -988,8 +988,7 @@ def restricted_automorphism_group(self, vertex_labels=None): sage: set(G.domain()) == set(Z3square.vertices()) # optional - sage.groups sage.graphs True sage: (set(tuple(x) for x in G.orbit(Z3square.vertices()[0])) # optional - sage.groups sage.graphs - ....: == set([(0, 0), (1, 2), (3, 3), (2, 1)]) - + ....: == set([(0, 0), (1, 2), (3, 3), (2, 1)])) True sage: cell24 = LatticePolytope_PPL( ....: (1,0,0,0), (0,1,0,0), (0,0,1,0), (0,0,0,1), (1,-1,-1,1), (0,0,-1,1), diff --git a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py index ab547996f84..0253cdc1888 100644 --- a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py +++ b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py @@ -85,7 +85,8 @@ class ParametrizedSurface3D(SageObject): explicitly specifying its parametric equation:: sage: u, v = var('u,v', domain='real') - sage: eparaboloid = ParametrizedSurface3D((u, v, u^2 + v^2), (u, v),'elliptic paraboloid'); eparaboloid + sage: eparaboloid = ParametrizedSurface3D((u, v, u^2 + v^2), (u, v), + ....: 'elliptic paraboloid'); eparaboloid Parametrized surface ('elliptic paraboloid') with equation (u, v, u^2 + v^2) When the ranges for the intrinsic coordinates are known, they can be @@ -96,19 +97,24 @@ class ParametrizedSurface3D(SageObject): sage: coords = ((u1, -pi/2, pi/2), (u2, 0, pi)) sage: ellipsoid_eq = (cos(u1)*cos(u2), 2*sin(u1)*cos(u2), 3*sin(u2)) 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)) + Parametrized surface ('ellipsoid') with equation + (cos(u1)*cos(u2), 2*cos(u2)*sin(u1), 3*sin(u2)) sage: ellipsoid.plot() # optional - sage.plot Graphics3d Object Standard surfaces can be constructed using the ``surfaces`` generator:: 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)) + 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)) Latex representation of the surfaces:: sage: u, v = var('u, v', domain='real') - sage: sphere = ParametrizedSurface3D((cos(u)*cos(v), sin(u)*cos(v), sin(v)), (u, v), 'sphere') + sage: sphere = ParametrizedSurface3D((cos(u)*cos(v), sin(u)*cos(v), sin(v)), (u, v), + ....: 'sphere') sage: print(latex(sphere)) \left(\cos\left(u\right) \cos\left(v\right), \cos\left(v\right) \sin\left(u\right), \sin\left(v\right)\right) sage: print(sphere._latex_()) @@ -119,7 +125,8 @@ class ParametrizedSurface3D(SageObject): To plot a parametric surface, use the :meth:`plot` member function:: 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) + 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 Graphics3d Object @@ -131,11 +138,14 @@ class ParametrizedSurface3D(SageObject): sage: a, b, c = var('a, b, c', domain='real') sage: u1, u2 = var('u1, u2', domain='real') sage: ellipsoid_eq = (a*cos(u1)*cos(u2), b*sin(u1)*cos(u2), c*sin(u2)) - sage: ellipsoid = ParametrizedSurface3D(ellipsoid_eq, (u1, u2), 'Symbolic ellipsoid'); ellipsoid - Parametrized surface ('Symbolic ellipsoid') with equation (a*cos(u1)*cos(u2), b*cos(u2)*sin(u1), c*sin(u2)) + sage: ellipsoid = ParametrizedSurface3D(ellipsoid_eq, (u1, u2), + ....: 'Symbolic ellipsoid'); ellipsoid + Parametrized surface ('Symbolic ellipsoid') with equation + (a*cos(u1)*cos(u2), b*cos(u2)*sin(u1), c*sin(u2)) sage: ellipsoid.natural_frame() - {1: (-a*cos(u2)*sin(u1), b*cos(u1)*cos(u2), 0), 2: (-a*cos(u1)*sin(u2), -b*sin(u1)*sin(u2), c*cos(u2))} + {1: (-a*cos(u2)*sin(u1), b*cos(u1)*cos(u2), 0), + 2: (-a*cos(u1)*sin(u2), -b*sin(u1)*sin(u2), c*cos(u2))} We find the normal vector field to the surface. The normal vector field is the vector product of the vectors of the natural frame, @@ -148,7 +158,8 @@ class ParametrizedSurface3D(SageObject): the unit normal vector field of the elliptic paraboloid, we put:: sage: u, v = var('u,v', domain='real') - sage: eparaboloid = ParametrizedSurface3D([u,v,u^2+v^2],[u,v],'elliptic paraboloid') + sage: eparaboloid = ParametrizedSurface3D([u, v, u^2 + v^2], [u,v], + ....: 'elliptic paraboloid') sage: eparaboloid.normal_vector(normalized=True) (-2*u/sqrt(4*u^2 + 4*v^2 + 1), -2*v/sqrt(4*u^2 + 4*v^2 + 1), 1/sqrt(4*u^2 + 4*v^2 + 1)) @@ -156,7 +167,9 @@ class ParametrizedSurface3D(SageObject): sage: u, v = var('u, v', domain='real') sage: a, b = var('a, b', domain='real') - sage: torus = ParametrizedSurface3D(((a + b*cos(u))*cos(v),(a + b*cos(u))*sin(v), b*sin(u)),[u,v],'torus') + sage: torus = ParametrizedSurface3D(((a + b*cos(u))*cos(v), + ....: (a + b*cos(u))*sin(v), + ....: b*sin(u)), [u,v], 'torus') sage: torus.first_fundamental_form_coefficients() {(1, 1): b^2, (1, 2): 0, (2, 1): 0, (2, 2): b^2*cos(u)^2 + 2*a*b*cos(u) + a^2} @@ -179,7 +192,7 @@ class ParametrizedSurface3D(SageObject): Once we specify numerical values for the axes of the ellipsoid, we can determine the numerical value of the length integral:: - sage: L = sqrt(ellipsoid.first_fundamental_form(du, du).substitute(u1=u1,u2=u2)) + sage: L = sqrt(ellipsoid.first_fundamental_form(du, du).substitute(u1=u1, u2=u2)) sage: numerical_integral(L.substitute(a=2, b=1.5, c=1),0,1)[0] # rel tol 1e-11 2.00127905972 @@ -189,8 +202,9 @@ class ParametrizedSurface3D(SageObject): sage: u, v = var('u,v', domain='real') sage: assume(R>0) sage: assume(cos(v)>0) - sage: sphere = ParametrizedSurface3D([R*cos(u)*cos(v),R*sin(u)*cos(v),R*sin(v)],[u,v],'sphere') - sage: integral(integral(sphere.area_form(),u,0,2*pi),v,-pi/2,pi/2) + sage: sphere = ParametrizedSurface3D([R*cos(u)*cos(v), R*sin(u)*cos(v), R*sin(v)], + ....: [u,v], 'sphere') + sage: integral(integral(sphere.area_form(), u, 0, 2*pi), v, -pi/2, pi/2) 4*pi*R^2 We can find an orthonormal frame field `\{e_1, e_2\}` of a surface @@ -198,9 +212,13 @@ class ParametrizedSurface3D(SageObject): orthonormal frame field for the elliptic paraboloid:: sage: u, v = var('u,v', domain='real') - sage: eparaboloid = ParametrizedSurface3D([u,v,u^2+v^2],[u,v],'elliptic paraboloid') + sage: eparaboloid = ParametrizedSurface3D([u, v, u^2 + v^2], [u,v], + ....: 'elliptic paraboloid') sage: eparaboloid.orthonormal_frame() - {1: (1/sqrt(4*u^2 + 1), 0, 2*u/sqrt(4*u^2 + 1)), 2: (-4*u*v/(sqrt(4*u^2 + 4*v^2 + 1)*sqrt(4*u^2 + 1)), sqrt(4*u^2 + 1)/sqrt(4*u^2 + 4*v^2 + 1), 2*v/(sqrt(4*u^2 + 4*v^2 + 1)*sqrt(4*u^2 + 1)))} + {1: (1/sqrt(4*u^2 + 1), 0, 2*u/sqrt(4*u^2 + 1)), + 2: (-4*u*v/(sqrt(4*u^2 + 4*v^2 + 1)*sqrt(4*u^2 + 1)), + sqrt(4*u^2 + 1)/sqrt(4*u^2 + 4*v^2 + 1), + 2*v/(sqrt(4*u^2 + 4*v^2 + 1)*sqrt(4*u^2 + 1)))} We can express the orthogonal frame field both in exterior coordinates (i.e. expressed as vector field fields in the ambient @@ -209,7 +227,9 @@ class ParametrizedSurface3D(SageObject): coordinates:: sage: eparaboloid.orthonormal_frame(coordinates='int') - {1: (1/sqrt(4*u^2 + 1), 0), 2: (-4*u*v/(sqrt(4*u^2 + 4*v^2 + 1)*sqrt(4*u^2 + 1)), sqrt(4*u^2 + 1)/sqrt(4*u^2 + 4*v^2 + 1))} + {1: (1/sqrt(4*u^2 + 1), 0), + 2: (-4*u*v/(sqrt(4*u^2 + 4*v^2 + 1)*sqrt(4*u^2 + 1)), + sqrt(4*u^2 + 1)/sqrt(4*u^2 + 4*v^2 + 1))} Using the orthonormal frame in interior coordinates, we can calculate the structure functions `c^k_{ij}` of the surface, defined by @@ -227,9 +247,9 @@ class ParametrizedSurface3D(SageObject): sage: sphere = surfaces.Sphere(); sphere Parametrized surface ('Sphere') with equation (cos(u)*cos(v), cos(v)*sin(u), sin(v)) - sage: K = sphere.gauss_curvature(); K # Not tested -- see trac 12737 + sage: K = sphere.gauss_curvature(); K # Not tested -- see trac 12737 1 - sage: H = sphere.mean_curvature(); H # Not tested -- see trac 12737 + sage: H = sphere.mean_curvature(); H # Not tested -- see trac 12737 -1 We can easily generate a color plot of the Gaussian curvature of a surface. @@ -238,57 +258,57 @@ class ParametrizedSurface3D(SageObject): 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)] - sage: ellipsoid = ParametrizedSurface3D(ellipsoid_equation(u1,u2), [u1, u2],'ellipsoid') + sage: ellipsoid = ParametrizedSurface3D(ellipsoid_equation(u1,u2), [u1, u2], 'ellipsoid') sage: # set intervals for variables and the number of division points sage: u1min, u1max = -1.5, 1.5 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 # 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: # 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() # 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: # 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) # optional - numpy + sage: K_min = min(K_array) # optional - numpy 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],u_array[counter][1]) + 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 + ....: u_array[counter][1]) ....: for counter in range(0,len(u_array))] - sage: curvature_ellipsoid_plot = sum(point([xx for xx in points_array[counter]], # optional - numpy sage.plot + sage: curvature_ellipsoid_plot = sum(point([xx # optional - numpy 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) # optional - numpy sage.plot We can find the principal curvatures and principal directions of the elliptic paraboloid:: sage: u, v = var('u, v', domain='real') - sage: eparaboloid = ParametrizedSurface3D([u, v, u^2+v^2], [u, v], 'elliptic paraboloid') + sage: eparaboloid = ParametrizedSurface3D([u, v, u^2+v^2], [u, v], + ....: 'elliptic paraboloid') sage: pd = eparaboloid.principal_directions(); pd - [(2*sqrt(4*u^2 + 4*v^2 + 1)/(16*u^4 + 16*v^4 + 8*(4*u^2 + 1)*v^2 + 8*u^2 + 1), [(1, v/u)], 1), (2/sqrt(4*u^2 + 4*v^2 + 1), [(1, -u/v)], 1)] + [(2*sqrt(4*u^2 + 4*v^2 + 1)/(16*u^4 + 16*v^4 + 8*(4*u^2 + 1)*v^2 + 8*u^2 + 1), [(1, v/u)], 1), + (2/sqrt(4*u^2 + 4*v^2 + 1), [(1, -u/v)], 1)] We extract the principal curvatures:: - sage: k1 = pd[0][0].simplify_full() - sage: k1 + sage: k1 = pd[0][0].simplify_full(); k1 2*sqrt(4*u^2 + 4*v^2 + 1)/(16*u^4 + 16*v^4 + 8*(4*u^2 + 1)*v^2 + 8*u^2 + 1) - sage: k2 = pd[1][0].simplify_full() - sage: k2 + sage: k2 = pd[1][0].simplify_full(); k2 2/sqrt(4*u^2 + 4*v^2 + 1) and check them by comparison with the Gaussian and mean curvature expressed in terms of the principal curvatures:: - sage: K = eparaboloid.gauss_curvature().simplify_full() - sage: K + sage: K = eparaboloid.gauss_curvature().simplify_full(); K 4/(16*u^4 + 16*v^4 + 8*(4*u^2 + 1)*v^2 + 8*u^2 + 1) - sage: H = eparaboloid.mean_curvature().simplify_full() - sage: H + sage: H = eparaboloid.mean_curvature().simplify_full(); H 2*(2*u^2 + 2*v^2 + 1)/(4*u^2 + 4*v^2 + 1)^(3/2) sage: (K - k1*k2).simplify_full() 0 @@ -314,10 +334,15 @@ class ParametrizedSurface3D(SageObject): that these points are conjugate:: sage: S = surfaces.Sphere() - sage: g1 = [c[-1] for c in S.geodesics_numerical((0,0),(1,0),(0,2*pi,100))] - sage: g2 = [c[-1] for c in S.geodesics_numerical((0,0),(cos(pi/3),sin(pi/3)),(0,2*pi,100))] - 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') + line3d(g2,color='red') + line3d(g3,color='red')).show() # optional - sage.plot + sage: g1 = [c[-1] for c in S.geodesics_numerical((0,0), (1,0), (0,2*pi,100))] + sage: g2 = [c[-1] for c in S.geodesics_numerical((0,0), + ....: (cos(pi/3),sin(pi/3)), + ....: (0,2*pi,100))] + 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 + ....: + line3d(g2, color='red') + line3d(g3, color='red')).show() """ @@ -338,7 +363,8 @@ def __init__(self, equation, variables, name=None): 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'); enneper - Parametrized surface ('Enneper Surface') with equation (-u^3 + 3*u*v^2 + 3*u, 3*u^2*v - v^3 + 3*v, 3*u^2 - 3*v^2) + Parametrized surface ('Enneper Surface') with equation + (-u^3 + 3*u*v^2 + 3*u, 3*u^2*v - v^3 + 3*v, 3*u^2 - 3*v^2) """ self.equation = tuple(equation) @@ -407,7 +433,9 @@ def point(self, coords): EXAMPLES:: sage: u, v = var('u, v', domain='real') - sage: torus = ParametrizedSurface3D(((2 + cos(u))*cos(v),(2 + cos(u))*sin(v), sin(u)),[u,v],'torus') + sage: torus = ParametrizedSurface3D(((2 + cos(u))*cos(v), + ....: (2 + cos(u))*sin(v), + ....: sin(u)), [u,v], 'torus') sage: torus.point((0, pi/2)) (0, 3, 0) sage: torus.point((pi/2, pi)) @@ -444,7 +472,7 @@ def tangent_vector(self, coords, components): 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: e = ParametrizedSurface3D(eq, (u, v),'Enneper Surface') + sage: e = ParametrizedSurface3D(eq, (u, v), 'Enneper Surface') sage: w1 = e.tangent_vector((1, 2), (1, 0)); w1 (12, 12, 6) @@ -524,7 +552,8 @@ def natural_frame(self): EXAMPLES:: sage: u, v = var('u, v', domain='real') - sage: eparaboloid = ParametrizedSurface3D((u, v, u^2+v^2), (u, v), 'elliptic paraboloid') + sage: eparaboloid = ParametrizedSurface3D((u, v, u^2+v^2), (u, v), + ....: 'elliptic paraboloid') sage: eparaboloid.natural_frame() {1: (1, 0, 2*u), 2: (0, 1, 2*v)} """ @@ -554,11 +583,14 @@ def normal_vector(self, normalized=False): EXAMPLES:: sage: u, v = var('u, v', domain='real') - sage: eparaboloid = ParametrizedSurface3D((u, v, u^2 + v^2), (u, v), 'elliptic paraboloid') + sage: eparaboloid = ParametrizedSurface3D((u, v, u^2 + v^2), (u, v), + ....: 'elliptic paraboloid') sage: eparaboloid.normal_vector(normalized=False) (-2*u, -2*v, 1) sage: eparaboloid.normal_vector(normalized=True) - (-2*u/sqrt(4*u^2 + 4*v^2 + 1), -2*v/sqrt(4*u^2 + 4*v^2 + 1), 1/sqrt(4*u^2 + 4*v^2 + 1)) + (-2*u/sqrt(4*u^2 + 4*v^2 + 1), + -2*v/sqrt(4*u^2 + 4*v^2 + 1), + 1/sqrt(4*u^2 + 4*v^2 + 1)) """ From 961f55a4dda9f5ebd1ea33e1ebc58591ca5eafac Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 23 May 2023 18:37:48 -0700 Subject: [PATCH 4/5] src/sage/geometry/cone.py: Fix # optional --- src/sage/geometry/cone.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/geometry/cone.py b/src/sage/geometry/cone.py index 2b796e3de1a..2b500604138 100644 --- a/src/sage/geometry/cone.py +++ b/src/sage/geometry/cone.py @@ -1684,7 +1684,7 @@ def _contains(self, point, region='whole cone'): sage: c = Cone([(1,0), (0,1)]) sage: c._contains((1,I)) # optional - sage.symbolic False - sage: c._contains(vector(QQbar, [1,I])) # optional - sage.symbolic + sage: c._contains(vector(QQbar, [1,I])) # optional - sage.rings.number_field False And we refuse to coerce elements of another lattice into ours:: From 2be9942b429d89f278f438905e89fdabad7053b6 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 23 May 2023 23:23:44 -0700 Subject: [PATCH 5/5] src/sage/geometry/cone.py: Fix # optional --- src/sage/geometry/cone.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/geometry/cone.py b/src/sage/geometry/cone.py index 2b500604138..80c7dc63613 100644 --- a/src/sage/geometry/cone.py +++ b/src/sage/geometry/cone.py @@ -1684,7 +1684,7 @@ def _contains(self, point, region='whole cone'): sage: c = Cone([(1,0), (0,1)]) sage: c._contains((1,I)) # optional - sage.symbolic False - sage: c._contains(vector(QQbar, [1,I])) # optional - sage.rings.number_field + sage: c._contains(vector(QQbar, [1,I])) # optional - sage.rings.number_field sage.symbolic False And we refuse to coerce elements of another lattice into ours::