From 7ecdd57bf0263a60458a6adfec53e8a68c913352 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 26 Jan 2023 20:54:48 -0800 Subject: [PATCH 1/8] src/sage/geometry/polyhedron: Add # optional - sage.combinat, sage.groups, sage.plot, sage.rings.number_field, sage.symbolic --- .../polyhedron/backend_number_field.py | 6 +- src/sage/geometry/polyhedron/base.py | 16 +- src/sage/geometry/polyhedron/base2.py | 36 ++-- src/sage/geometry/polyhedron/base5.py | 24 +-- src/sage/geometry/polyhedron/base6.py | 78 ++++----- src/sage/geometry/polyhedron/base7.py | 42 ++--- src/sage/geometry/polyhedron/constructor.py | 8 +- .../polyhedron/generating_function.py | 1 + src/sage/geometry/polyhedron/library.py | 159 +++++++++--------- src/sage/geometry/polyhedron/parent.py | 14 +- src/sage/geometry/polyhedron/plot.py | 105 ++++++------ src/sage/numerical/all__sagemath_polyhedra.py | 9 + .../backends/all__sagemath_polyhedra.py | 0 13 files changed, 263 insertions(+), 235 deletions(-) create mode 100644 src/sage/numerical/all__sagemath_polyhedra.py create mode 100644 src/sage/numerical/backends/all__sagemath_polyhedra.py diff --git a/src/sage/geometry/polyhedron/backend_number_field.py b/src/sage/geometry/polyhedron/backend_number_field.py index 437550de3aa..a963ad9d770 100644 --- a/src/sage/geometry/polyhedron/backend_number_field.py +++ b/src/sage/geometry/polyhedron/backend_number_field.py @@ -119,11 +119,11 @@ def _init_from_Vrepresentation(self, vertices, rays, lines, Check that the coordinates of a vertex get simplified in the Symbolic Ring:: - sage: p = Polyhedron(ambient_dim=2, base_ring=SR, backend='number_field') + sage: p = Polyhedron(ambient_dim=2, base_ring=SR, backend='number_field') # optional - sage.symbolic sage: from sage.geometry.polyhedron.backend_number_field import Polyhedron_number_field - sage: Polyhedron_number_field._init_from_Vrepresentation(p, [(0,1/2),(sqrt(2),0),(4,5/6)], [], []); p + sage: Polyhedron_number_field._init_from_Vrepresentation(p, [(0,1/2),(sqrt(2),0),(4,5/6)], [], []); p # optional - sage.symbolic A 2-dimensional polyhedron in (Symbolic Ring)^2 defined as the convex hull of 3 vertices - sage: p.vertices()[0][0] + sage: p.vertices()[0][0] # optional - sage.symbolic 0 """ (vertices, rays, lines), internal_base_ring \ diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 77a11c53d21..9704f6ea607 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -318,11 +318,11 @@ def boundary_complex(self): sage: oc = polytopes.octahedron() sage: sc_oc = oc.boundary_complex() - sage: fl_oc = oc.face_lattice() - sage: fl_sc = sc_oc.face_poset() - sage: [len(x) for x in fl_oc.level_sets()] + 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 [1, 6, 12, 8, 1] - sage: [len(x) for x in fl_sc.level_sets()] + sage: [len(x) for x in fl_sc.level_sets()] # optional - sage.combinat [6, 12, 8] sage: sc_oc.euler_characteristic() 2 @@ -1056,7 +1056,7 @@ def bounding_box(self, integral=False, integral_hull=False): (None, None) sage: Polyhedron([ (1/3,2/3), (3/3, 4/3) ]).bounding_box(integral_hull=True) ((1, 1), (1, 1)) - sage: polytopes.buckyball(exact=False).bounding_box() + sage: polytopes.buckyball(exact=False).bounding_box() # optional - sage.groups ((-0.8090169944, -0.8090169944, -0.8090169944), (0.8090169944, 0.8090169944, 0.8090169944)) TESTS:: @@ -1161,12 +1161,12 @@ def _polymake_init_(self): Floating-point polyhedron:: - sage: P = polytopes.dodecahedron(exact=False); P + 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 + sage: print("There may be a recompilation warning"); PP = polymake(P); PP # optional - jupymake # optional - sage.groups There may be a recompilation warning... Polytope[...] - sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake + sage: sorted(PP.VERTICES[:], key=repr)[0] # optional - jupymake # optional - 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 9afeeaaef1f..fa0765795cb 100644 --- a/src/sage/geometry/polyhedron/base2.py +++ b/src/sage/geometry/polyhedron/base2.py @@ -262,21 +262,21 @@ def h_star_vector(self): volume = `\frac{1}{dim(S)!}`) is always 1. Here we test this on simplices up to dimension 3:: - sage: s1 = polytopes.simplex(1,backend='normaliz') # optional - pynormaliz - sage: s2 = polytopes.simplex(2,backend='normaliz') # optional - pynormaliz - sage: s3 = polytopes.simplex(3,backend='normaliz') # optional - pynormaliz - sage: [s1.h_star_vector(),s2.h_star_vector(),s3.h_star_vector()] # optional - pynormaliz + sage: s1 = polytopes.simplex(1,backend='normaliz') # optional - pynormaliz + sage: s2 = polytopes.simplex(2,backend='normaliz') # optional - pynormaliz + sage: s3 = polytopes.simplex(3,backend='normaliz') # optional - pynormaliz + sage: [s1.h_star_vector(), s2.h_star_vector(), s3.h_star_vector()] # optional - pynormaliz [[1], [1], [1]] For a less trivial example, we compute the `h^*`-vector of the `0/1`-cube, which has the Eulerian numbers `(3,i)` for `i \in [0,2]` as an `h^*`-vector:: - 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') # optional - pynormaliz + sage: cube.h_star_vector() # optional - pynormaliz [1, 4, 1] - sage: from sage.combinat.combinat import eulerian_number - sage: [eulerian_number(3,i) for i in range(3)] + sage: from sage.combinat.combinat import eulerian_number # optional - sage.combinat + sage: [eulerian_number(3,i) for i in range(3)] # optional - sage.combinat [1, 4, 1] TESTS:: @@ -293,8 +293,8 @@ def h_star_vector(self): ... TypeError: The h_star vector is only defined for lattice polytopes - sage: t2 = Polyhedron(vertices=[[AA(sqrt(2))],[1/2]]) - sage: t2.h_star_vector() + sage: t2 = Polyhedron(vertices=[[AA(sqrt(2))], [1/2]]) # optional - sage.rings.number_field + sage: t2.h_star_vector() # optional - sage.rings.number_field Traceback (most recent call last): ... TypeError: The h_star vector is only defined for lattice polytopes @@ -767,15 +767,15 @@ def generating_function_of_integral_points(self, **kwds): sage: P2 = ( ....: Polyhedron(ieqs=[(0, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, -1)]), ....: Polyhedron(ieqs=[(0, -1, 0, 1), (0, 1, 0, 0), (0, 0, 1, 0)])) - sage: P2[0].generating_function_of_integral_points(sort_factors=True) + sage: P2[0].generating_function_of_integral_points(sort_factors=True) # optional - sage.combinat 1 * (-y0 + 1)^-1 * (-y1 + 1)^-1 * (-y0*y2 + 1)^-1 - sage: P2[1].generating_function_of_integral_points(sort_factors=True) + sage: P2[1].generating_function_of_integral_points(sort_factors=True) # optional - sage.combinat 1 * (-y1 + 1)^-1 * (-y2 + 1)^-1 * (-y0*y2 + 1)^-1 sage: (P2[0] & P2[1]).Hrepresentation() (An equation (1, 0, -1) x + 0 == 0, An inequality (1, 0, 0) x + 0 >= 0, An inequality (0, 1, 0) x + 0 >= 0) - sage: (P2[0] & P2[1]).generating_function_of_integral_points(sort_factors=True) + sage: (P2[0] & P2[1]).generating_function_of_integral_points(sort_factors=True) # optional - sage.combinat 1 * (-y1 + 1)^-1 * (-y0*y2 + 1)^-1 The number of integer partitions @@ -784,16 +784,16 @@ def generating_function_of_integral_points(self, **kwds): sage: P = Polyhedron(ieqs=[(-1, 1, 0, 0, 0, 0), (0, -1, 1, 0, 0, 0), ....: (0, 0, -1, 1, 0, 0), (0, 0, 0, -1, 1, 0), ....: (0, 0, 0, 0, -1, 1)]) - sage: f = P.generating_function_of_integral_points(sort_factors=True); f + sage: f = P.generating_function_of_integral_points(sort_factors=True); f # optional - sage.combinat y0*y1*y2*y3*y4 * (-y4 + 1)^-1 * (-y3*y4 + 1)^-1 * (-y2*y3*y4 + 1)^-1 * (-y1*y2*y3*y4 + 1)^-1 * (-y0*y1*y2*y3*y4 + 1)^-1 - sage: f = f.value() - sage: P. = PowerSeriesRing(ZZ) - sage: c = f.subs({y: z for y in f.parent().gens()}); c + sage: f = f.value() # optional - sage.combinat + sage: P. = PowerSeriesRing(ZZ) # optional - sage.combinat + sage: c = f.subs({y: z for y in f.parent().gens()}); c # optional - sage.combinat z^5 + z^6 + 2*z^7 + 3*z^8 + 5*z^9 + 7*z^10 + 10*z^11 + 13*z^12 + 18*z^13 + 23*z^14 + 30*z^15 + 37*z^16 + 47*z^17 + 57*z^18 + 70*z^19 + 84*z^20 + 101*z^21 + 119*z^22 + 141*z^23 + 164*z^24 + O(z^25) - sage: [Partitions(k, length=5).cardinality() for k in range(5,20)] == \ + sage: [Partitions(k, length=5).cardinality() for k in range(5,20)] == \ # optional - sage.combinat ....: c.truncate().coefficients(sparse=False)[5:20] True diff --git a/src/sage/geometry/polyhedron/base5.py b/src/sage/geometry/polyhedron/base5.py index 04d1fa0314b..d83a1593e54 100644 --- a/src/sage/geometry/polyhedron/base5.py +++ b/src/sage/geometry/polyhedron/base5.py @@ -1348,11 +1348,13 @@ def intersection(self, other): Check that :trac:`19012` is fixed:: - sage: K. = QuadraticField(5) - sage: P = Polyhedron([[0,0],[0,a],[1,1]]) - sage: Q = Polyhedron(ieqs=[[-1,a,1]]) - sage: P.intersection(Q) - A 2-dimensional polyhedron in (Number Field in a with defining polynomial x^2 - 5 with a = 2.236067977499790?)^2 defined as the convex hull of 4 vertices + 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 """ new_ieqs = self.inequalities() + other.inequalities() new_eqns = self.equations() + other.equations() @@ -1993,7 +1995,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()) + sage: face_trunc.face_lattice().is_isomorphic(Cube.face_lattice()) # optional - sage.combinat True TESTS: @@ -2227,10 +2229,10 @@ def wedge(self, face, width=1): sage: W1.is_combinatorially_isomorphic(triangular_prism) # optional - sage.graphs # optional - sage.rings.number_field True - sage: Q = polytopes.hypersimplex(4,2) - sage: W2 = Q.wedge(Q.faces(2)[7]); W2 + 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() + 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), @@ -2241,9 +2243,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 + 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() + 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), diff --git a/src/sage/geometry/polyhedron/base6.py b/src/sage/geometry/polyhedron/base6.py index 2dd1117ad79..a279898247e 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) + sage: Polyhedron_base6.plot(P) # optional - sage.plot Graphics3d Object - sage: print(Polyhedron_base6.tikz(P, output_type='TikzPicture')) + 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) + sage: Polyhedron_base6.show(Q) # optional - sage.plot sage: Polyhedron_base6.schlegel_projection(Q) The projection of a polyhedron into 3 dimensions @@ -383,25 +383,25 @@ def plot(self, sage: halfspace = Polyhedron(rays=[(0, 0, 1)], lines=[(1, 0, 0), (0, 1, 0)]) sage: len(halfspace.projection().arrows) 5 - sage: halfspace.plot(fill=(0,1,0)) + sage: halfspace.plot(fill=(0, 1, 0)) # optional - sage.plot Graphics3d Object sage: fullspace = Polyhedron(lines=[(1, 0, 0), (0, 1, 0), (0, 0, 1)]) sage: len(fullspace.projection().arrows) 6 - sage: fullspace.plot(color=(1,0,0), alpha=0.5) + sage: fullspace.plot(color=(1, 0, 0), alpha=0.5) # optional - sage.plot Graphics3d Object sage: cone = Polyhedron(rays=[(1, 0, 0), (0, 1, 0), (0, 0, 1)]) - sage: cone.plot(fill='rainbow', alpha=0.6) + sage: cone.plot(fill='rainbow', alpha=0.6) # optional - sage.plot Graphics3d Object - sage: p = Polyhedron(vertices=[(0,0,0),(1,0,0)],rays=[(-1,1,0),(1,1,0),(0,0,1)]) - sage: p.plot(fill='mediumspringgreen', point='red', size=30, width=2) + sage: p = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0)], rays=[(-1, 1, 0), (1, 1, 0), (0, 0, 1)]) + sage: p.plot(fill='mediumspringgreen', point='red', size=30, width=2) # optional - sage.plot Graphics3d Object - sage: cylinder = Polyhedron(vertices = [(0, 0, 0), (1, 0, 0), (0, 1, 0)], lines=[(0, 0, 1)]) - sage: cylinder.plot(fill='red') # check it is not all black + sage: cylinder = Polyhedron(vertices=[(0, 0, 0), (1, 0, 0), (0, 1, 0)], lines=[(0, 0, 1)]) + sage: cylinder.plot(fill='red') # check it is not all black # optional - sage.plot Graphics3d Object - sage: quarter = Polyhedron(rays = [(-1, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)]) - sage: quarter.plot(fill='rainbow') # check it is not all black nor with too many colors + sage: quarter = Polyhedron(rays=[(-1, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1)]) + sage: quarter.plot(fill='rainbow') # check it is not all black nor with too many colors # optional - sage.plot Graphics3d Object """ def merge_options(*opts): @@ -545,8 +545,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') - sage: Img + 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 +563,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])) + 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 @@ -582,8 +582,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') - sage: t + 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 +600,7 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% \end{tikzpicture} \end{document} - sage: path_to_file = t.pdf() # not tested + sage: path_to_file = t.pdf() # not tested # optional - sage.plot """ return self.projection().tikz(view, angle, scale, @@ -692,8 +692,8 @@ def gale_transform(self): Check that :trac:`29073` is fixed:: - sage: P = polytopes.icosahedron(exact=False) - sage: sum(P.gale_transform()).norm() < 1e-15 + 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 +784,8 @@ def render_solid(self, **kwds): EXAMPLES:: sage: p = polytopes.hypercube(3) - sage: p_solid = p.render_solid(opacity = .7) - sage: type(p_solid) + sage: p_solid = p.render_solid(opacity=.7) # optional - sage.plot + sage: type(p_solid) # optional - sage.plot """ proj = self.projection() @@ -803,8 +803,8 @@ def render_wireframe(self, **kwds): EXAMPLES:: sage: p = Polyhedron([[1,2,],[1,1],[0,0]]) - sage: p_wireframe = p.render_wireframe() - sage: p_wireframe._objects + 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() @@ -1562,44 +1562,44 @@ def affine_hull_manifold(self, name=None, latex_name=None, start_index=0, ambien EXAMPLES:: - sage: triangle = Polyhedron([(1,0,0), (0,1,0), (0,0,1)]); triangle + 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 + 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() + 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() + sage: A.embedding().inverse().display() # optional - sage.symbolic E^3 → A (x, y, z) ↦ (x0, x1) = (x, y) - sage: A.adapted_chart() + sage: A.adapted_chart() # optional - sage.symbolic [Chart (E^3, (x0_E3, x1_E3, t0_E3))] - sage: A.normal().display() + 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 + 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() + 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 + 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() + 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() + 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 - sage: submanifolds = [ # optional - sage.rings.number_field + sage: E3 = EuclideanSpace(3) # optional - sage.rings.number_field # optional - sage.symbolic + sage: submanifolds = [ # optional - sage.rings.number_field # optional - 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 # optional - sage.plot # optional - sage.rings.number_field + sage: sum(FM.plot({}, srange(-2, 2, 0.1), srange(-2, 2, 0.1), opacity=0.2) # not tested # optional - sage.symbolic # optional - sage.plot # optional - sage.rings.number_field ....: for FM in submanifolds) + D.plot() Graphics3d Object @@ -1607,7 +1607,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() + 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 db828e2eb0a..021eaa679ac 100644 --- a/src/sage/geometry/polyhedron/base7.py +++ b/src/sage/geometry/polyhedron/base7.py @@ -44,12 +44,15 @@ class Polyhedron_base7(Polyhedron_base6): TESTS:: sage: from sage.geometry.polyhedron.base7 import Polyhedron_base7 - sage: P = polytopes.associahedron(['A', 3]) - sage: Polyhedron_base7.centroid(P) + 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) - (<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') + 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 79/3 """ @cached_method(do_pickle=True) @@ -88,8 +91,8 @@ def centroid(self, engine='auto', **kwds): sage: P.centroid() (1/4, 0, 0) - sage: P = polytopes.associahedron(['A',2]) - sage: P.centroid() + 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 @@ -98,7 +101,7 @@ def centroid(self, engine='auto', **kwds): The method is not implemented for unbounded polyhedra:: - sage: P = Polyhedron(vertices=[(0,0)],rays=[(1,0),(0,1)]) + sage: P = Polyhedron(vertices=[(0, 0)], rays=[(1, 0), (0, 1)]) sage: P.centroid() Traceback (most recent call last): ... @@ -521,7 +524,7 @@ def volume(self, measure='ambient', engine='auto', **kwds): sage: P = Polyhedron([[0, 0], [1, 1]]) sage: P.volume() 0 - sage: P.volume(measure='induced') + sage: P.volume(measure='induced') # optional - sage.rings.number_field 1.414213562373095? sage: P.volume(measure='induced_rational') # optional -- latte_int 1 @@ -556,19 +559,19 @@ def volume(self, measure='ambient', engine='auto', **kwds): sage: P.volume(measure='induced_lattice',engine='latte') # optional - latte_int 3 - sage: Dexact = polytopes.dodecahedron() # optional - sage.rings.number_field - sage: v = Dexact.faces(2)[0].as_polyhedron().volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field + 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 1.53406271079097? - sage: v = Dexact.faces(2)[4].as_polyhedron().volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field + sage: v = Dexact.faces(2)[4].as_polyhedron().volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field # optional - sage.groups 1.53406271079097? - sage: RDF(v) # abs tol 1e-9 # optional - sage.rings.number_field + sage: RDF(v) # abs tol 1e-9 # optional - sage.rings.number_field # optional - sage.groups 1.53406271079044 - sage: Dinexact = polytopes.dodecahedron(exact=False) - sage: w = Dinexact.faces(2)[2].as_polyhedron().volume(measure='induced', engine='internal'); RDF(w) # abs tol 1e-9 + 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 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)] + 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 True sage: I = Polyhedron([[-3, 0], [0, 9]]) @@ -804,9 +807,9 @@ def integrate(self, function, measure='ambient', **kwds): sage: R. = QQ[] sage: P = polytopes.simplex(2) - sage: V = AA(P.volume(measure='induced')); V.radical_expression() + sage: V = AA(P.volume(measure='induced')); 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 + sage: P.integrate(R(1), measure='induced') == V # optional - latte_int # optional - sage.rings.number_field sage.symbolic True Computing the mass center:: @@ -951,7 +954,6 @@ def _integrate_latte_(self, polynomial, **kwds): sage: Polyhedron(vertices=[()]).integrate(R(42)) 42 """ - from sage.interfaces.latte import integrate from sage.rings.real_double import RDF if self.base_ring() == RDF: @@ -961,6 +963,8 @@ def _integrate_latte_(self, polynomial, **kwds): assert len(self.vertices()) == 1 vertex = tuple(vertices[0]) return polynomial(vertex) + + from sage.interfaces.latte import integrate return integrate(self.cdd_Hrepresentation(), polynomial, cdd=True, **kwds) diff --git a/src/sage/geometry/polyhedron/constructor.py b/src/sage/geometry/polyhedron/constructor.py index 7f11ac13593..971e36388f4 100644 --- a/src/sage/geometry/polyhedron/constructor.py +++ b/src/sage/geometry/polyhedron/constructor.py @@ -504,12 +504,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) - sage: h = x + y - 1; h + 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) + 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) + 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:: diff --git a/src/sage/geometry/polyhedron/generating_function.py b/src/sage/geometry/polyhedron/generating_function.py index 9fadd8f3e13..2c6cfccf200 100644 --- a/src/sage/geometry/polyhedron/generating_function.py +++ b/src/sage/geometry/polyhedron/generating_function.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.combinat r""" Generating Function of Polyhedron's Integral Points diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py index e54d8a7efd1..f9fb4e192cd 100644 --- a/src/sage/geometry/polyhedron/library.py +++ b/src/sage/geometry/polyhedron/library.py @@ -1218,28 +1218,28 @@ def truncated_octahedron(self, backend=None): EXAMPLES:: - sage: co = polytopes.truncated_octahedron() - sage: co.f_vector() + 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) + 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) + sage: sum(1 for f in co.facets() if len(f.vertices()) == 6) # optional - sage.combinat 8 Some more computation:: - sage: co.volume() + sage: co.volume() # optional - sage.combinat 32 - sage: co.ehrhart_polynomial() # optional - latte_int + sage: co.ehrhart_polynomial() # optional - latte_int # optional - sage.combinat 32*t^3 + 18*t^2 + 6*t + 1 TESTS:: - sage: to_norm = polytopes.truncated_octahedron(backend='normaliz') # optional - pynormaliz - sage: TestSuite(to_norm).run() # optional - pynormaliz + sage: to_norm = polytopes.truncated_octahedron(backend='normaliz') # optional - pynormaliz sage.combinat + sage: TestSuite(to_norm).run() # optional - pynormaliz sage.combinat """ v = [(0, e, f) for e in [-1, 1] for f in [-2, 2]] v = [(xyz[sigma(1) - 1], xyz[sigma(2) - 1], xyz[sigma(3) - 1]) @@ -1416,33 +1416,33 @@ def buckyball(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: bb = polytopes.buckyball() # long time - 6secs # optional - sage.rings.number_field - sage: bb.f_vector() # long time # optional - sage.rings.number_field + 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 (1, 60, 90, 32, 1) - sage: bb.base_ring() # long time # optional - sage.rings.number_field + 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? A much faster implementation using floating point approximations:: - sage: bb = polytopes.buckyball(exact=False) - sage: bb.f_vector() + 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() + 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) + 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) + 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 - pynormaliz # optional - sage.rings.number_field - sage: bb.f_vector() # optional - pynormaliz # optional - sage.rings.number_field + 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 (1, 60, 90, 32, 1) - sage: bb.base_ring() # optional - pynormaliz # optional - sage.rings.number_field + 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? """ @@ -1465,25 +1465,25 @@ def icosidodecahedron(self, exact=True, backend=None): EXAMPLES:: - sage: id = polytopes.icosidodecahedron() # optional - sage.rings.number_field - sage: id.f_vector() # optional - sage.rings.number_field + sage: id = polytopes.icosidodecahedron() # optional - sage.rings.number_field # optional - sage.groups + sage: id.f_vector() # optional - sage.rings.number_field # optional - sage.groups (1, 30, 60, 32, 1) TESTS:: - sage: id = polytopes.icosidodecahedron(exact=False); id + sage: id = polytopes.icosidodecahedron(exact=False); id # optional - sage.rings.number_field # optional - 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", + sage: TestSuite(id).run(skip=["_test_is_combinatorially_isomorphic", # optional - sage.rings.number_field # optional - sage.groups ....: "_test_product", ....: "_test_pyramid", ....: "_test_lawrence"]) - sage: id = polytopes.icosidodecahedron(backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field - sage: id.f_vector() # optional - pynormaliz # optional - sage.rings.number_field + 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 (1, 30, 60, 32, 1) - sage: id.base_ring() # optional - pynormaliz # optional - sage.rings.number_field + 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 + sage: TestSuite(id).run() # long time # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups """ from sage.rings.number_field.number_field import QuadraticField from itertools import product @@ -1694,15 +1694,15 @@ def pentakis_dodecahedron(self, exact=True, base_ring=None, backend=None): A much faster implementation is obtained when setting ``exact=False``:: - sage: pd = polytopes.pentakis_dodecahedron(exact=False) - sage: pd.n_vertices() + sage: pd = polytopes.pentakis_dodecahedron(exact=False) # optional - sage.groups + sage: pd.n_vertices() # optional - sage.groups 32 - sage: pd.n_inequalities() + sage: pd.n_inequalities() # optional - sage.groups 60 The 60 are triangles:: - sage: all(len(f.vertices()) == 3 for f in pd.facets()) + sage: all(len(f.vertices()) == 3 for f in pd.facets()) # optional - sage.groups True """ return self.buckyball(exact=exact, base_ring=base_ring, backend=backend).polar() @@ -2226,22 +2226,22 @@ def six_hundred_cell(self, exact=False, backend=None): EXAMPLES:: - sage: p600 = polytopes.six_hundred_cell() - sage: p600 + sage: p600 = polytopes.six_hundred_cell() # optional - sage.groups + sage: 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 + 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 - sage: len(list(p600.bounded_edges())) # not tested - very long time + 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 - sage: len(list(p600.bounded_edges())) # optional - pynormaliz, long time + 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 720 """ if exact: @@ -2297,8 +2297,8 @@ def grand_antiprism(self, exact=True, backend=None, verbose=False): Computation with the backend ``'normaliz'`` is instantaneous:: - sage: gap_norm = polytopes.grand_antiprism(backend='normaliz') # optional - pynormaliz - sage: gap_norm # optional - pynormaliz + 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 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 @@ -2516,7 +2516,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)) + 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 +2594,32 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula EXAMPLES:: - sage: perm_a3 = polytopes.generalized_permutahedron(['A',3]); perm_a3 + 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 + sage: perm_a3_011 = polytopes.generalized_permutahedron(['A',3],[0,1,1]); perm_a3_011 # optional - sage.combinat 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 + sage: perm_a3_110 = polytopes.generalized_permutahedron(['A',3],[1,1,0]); perm_a3_110 # optional - sage.combinat 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) True - sage: perm_a3_101 = polytopes.generalized_permutahedron(['A',3],[1,0,1]); perm_a3_101 + sage: perm_a3_101 = polytopes.generalized_permutahedron(['A',3],[1,0,1]); perm_a3_101 # optional - sage.combinat 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) + sage: perm_a3_110.is_combinatorially_isomorphic(perm_a3_101) # optional - sage.combinat False - sage: perm_a3_011.f_vector() + sage: perm_a3_011.f_vector() # optional - sage.combinat (1, 12, 18, 8, 1) - sage: perm_a3_101.f_vector() + 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]) - sage: perm_a2.vertices() + 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,7 +2629,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]); perm_b3 # long time # optional - sage.rings.number_field + 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 @@ -2639,8 +2639,8 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula rational coordinates. We first do the computations using floating point approximations (``RDF``):: - sage: perm_a2_inexact = polytopes.generalized_permutahedron(['A',2], exact=False) - sage: sorted(perm_a2_inexact.vertices()) + sage: perm_a2_inexact = polytopes.generalized_permutahedron(['A',2], exact=False) # optional - sage.combinat + 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,8 +2648,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, regular=True) - sage: sorted(perm_a2_inexact_reg.vertices()) + 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 [A vertex at (-1.0, 0.0), A vertex at (-0.5, -0.8660254038), A vertex at (-0.5, 0.8660254038), @@ -2659,8 +2660,8 @@ 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.rings.number_field - sage: V = sorted(perm_a2_reg.vertices()); V # random # optional - sage.rings.number_field + 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 [A vertex at (-1, 0), A vertex at (-1/2, -0.866025403784439?), A vertex at (-1/2, 0.866025403784439?), @@ -2671,60 +2672,60 @@ 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.rings.number_field + sage: for v in V: # optional - sage.combinat # optional - sage.rings.number_field ....: for x in v: ....: x.exactify() - sage: V # optional - sage.rings.number_field + sage: V # optional - sage.combinat # optional - 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.rings.number_field + sage: perm_a2_reg.is_inscribed() # optional - sage.combinat # optional - 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 + sage: perm_a3_reg = polytopes.generalized_permutahedron(['A',3], regular=True); perm_a3_reg # long time # optional - sage.rings.number_field # optional - sage.combinat A 3-dimensional polyhedron in AA^3 defined as the convex hull of 24 vertices - sage: perm_a3_reg.is_inscribed() # long time # optional - sage.rings.number_field + sage: perm_a3_reg.is_inscribed() # long time # optional - sage.rings.number_field # optional - sage.combinat True - sage: perm_b3_reg = polytopes.generalized_permutahedron(['B',3], regular=True); perm_b3_reg # not tested - long time (12sec on 64 bits). + 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) A 3-dimensional polyhedron in AA^3 defined as the convex hull of 48 vertices It is faster with the backend ``'number_field'``, which internally uses an embedded number field instead of doing the computations directly with the base ring (``AA``):: - sage: perm_a3_reg_nf = polytopes.generalized_permutahedron( # optional - sage.rings.number_field + sage: perm_a3_reg_nf = polytopes.generalized_permutahedron( # optional - sage.rings.number_field # optional - 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 + sage: perm_a3_reg_nf.is_inscribed() # optional - sage.rings.number_field # optional - sage.combinat True - sage: perm_b3_reg_nf = polytopes.generalized_permutahedron( # long time # optional - sage.rings.number_field + sage: perm_b3_reg_nf = polytopes.generalized_permutahedron( # long time # optional - sage.rings.number_field # optional - 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 + sage: perm_a3_reg_norm = polytopes.generalized_permutahedron( # optional - pynormaliz # optional - sage.rings.number_field # optional - 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 + sage: perm_a3_reg_norm.is_inscribed() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.combinat True - sage: perm_b3_reg_norm = polytopes.generalized_permutahedron( # optional - pynormaliz + sage: perm_b3_reg_norm = polytopes.generalized_permutahedron( # optional - pynormaliz # optional - sage.rings.number_field # optional - 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 - sage: perm_h3 # optional - pynormaliz + 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 defined as the convex hull of 120 vertices - sage: perm_f4 = polytopes.generalized_permutahedron(['F',4], backend='normaliz') # long time # optional - pynormaliz - sage: perm_f4 # long time # optional - pynormaliz + 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 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 @@ -2736,7 +2737,7 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula TESTS:: - sage: TestSuite(perm_h3).run() # optional - pynormaliz + sage: TestSuite(perm_h3).run() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.combinat """ from sage.combinat.root_system.coxeter_group import CoxeterGroup try: @@ -3225,7 +3226,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()]]) + 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') Traceback (most recent call last): ... @@ -3412,16 +3413,16 @@ def parallelotope(self, generators, backend=None): sage: polytopes.parallelotope([[1,2,3,4],[0,1,0,7],[3,1,0,2],[0,0,1,0]]) A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 16 vertices - sage: K = QuadraticField(2, 'sqrt2') - sage: sqrt2 = K.gen() - sage: P = polytopes.parallelotope([ (1,sqrt2), (1,-1) ]); P + 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() + 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/parent.py b/src/sage/geometry/polyhedron/parent.py index 2b87a343b41..8e2e868294d 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -858,16 +858,18 @@ def _coerce_base_ring(self, other): Test that :trac:`28770` is fixed:: sage: z = QQ['z'].0 - sage: K = NumberField(z^2 - 2,'s') - sage: triangle_QQ._coerce_base_ring(K) + 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()) + 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') - sage: K.gen()*polytopes.simplex(backend='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 + 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 """ from sage.structure.element import Element if isinstance(other, Element): diff --git a/src/sage/geometry/polyhedron/plot.py b/src/sage/geometry/polyhedron/plot.py index a4c30cadd0c..c53357404c6 100644 --- a/src/sage/geometry/polyhedron/plot.py +++ b/src/sage/geometry/polyhedron/plot.py @@ -341,23 +341,23 @@ def __init__(self, polyhedron, proj=projection_func_identity): EXAMPLES:: - sage: p = polytopes.icosahedron(exact=False) + sage: p = polytopes.icosahedron(exact=False) # optional - sage.groups sage: from sage.geometry.polyhedron.plot import Projection - sage: Projection(p) + sage: Projection(p) # optional - sage.groups The projection of a polyhedron into 3 dimensions sage: def pr_12(x): return [x[1],x[2]] - sage: Projection(p, pr_12) + sage: Projection(p, pr_12) # optional - sage.groups The projection of a polyhedron into 2 dimensions - sage: Projection(p, lambda x: [x[1],x[2]] ) # another way of doing the same projection + sage: Projection(p, lambda x: [x[1],x[2]] ) # another way of doing the same projection # optional - sage.groups The projection of a polyhedron into 2 dimensions - sage: _.plot() # plot of the projected icosahedron in 2d # optional - sage.plot + sage: _.plot() # plot of the projected icosahedron in 2d # optional - sage.plot # optional - sage.groups Graphics object consisting of 51 graphics primitives - sage: proj = Projection(p) - sage: proj.stereographic([1,2,3]) + sage: proj = Projection(p) # optional - sage.groups + sage: proj.stereographic([1,2,3]) # optional - sage.groups The projection of a polyhedron into 2 dimensions - sage: proj.plot() # optional - sage.plot + sage: proj.plot() # optional - sage.plot # optional - sage.groups Graphics object consisting of 51 graphics primitives - sage: TestSuite(proj).run(skip='_test_pickling') + sage: TestSuite(proj).run(skip='_test_pickling') # optional - sage.groups """ self.parent_polyhedron = polyhedron self.coords = Sequence([]) @@ -406,12 +406,12 @@ def __call__(self, proj=projection_func_identity): EXAMPLES:: - sage: p = polytopes.icosahedron(exact=False) + sage: p = polytopes.icosahedron(exact=False) # optional - sage.groups sage: from sage.geometry.polyhedron.plot import Projection - sage: pproj = Projection(p) + sage: pproj = Projection(p) # optional - sage.groups sage: from sage.geometry.polyhedron.plot import ProjectionFuncStereographic - sage: pproj_stereo = pproj.__call__(proj = ProjectionFuncStereographic([1,2,3])) - sage: sorted(pproj_stereo.polygons) + sage: pproj_stereo = pproj.__call__(proj=ProjectionFuncStereographic([1, 2, 3])) # optional - sage.groups + sage: sorted(pproj_stereo.polygons) # optional - sage.groups [[2, 0, 9], [3, 1, 10], [4, 0, 8], @@ -430,11 +430,11 @@ def identity(self): EXAMPLES:: - sage: p = polytopes.icosahedron(exact=False) + sage: p = polytopes.icosahedron(exact=False) # optional - sage.groups sage: from sage.geometry.polyhedron.plot import Projection - sage: pproj = Projection(p) - sage: ppid = pproj.identity() - sage: ppid.dimension + 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) @@ -952,10 +952,10 @@ def render_points_2d(self, **kwds): EXAMPLES:: - sage: hex = polytopes.regular_polygon(6) - sage: proj = hex.projection() - sage: hex_points = proj.render_points_2d() # optional - sage.plot - sage: hex_points._objects # optional - sage.plot + 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 [Point set defined by 6 point(s)] """ return point2d(self.coordinates_of(self.points), **kwds) @@ -966,9 +966,9 @@ def render_outline_2d(self, **kwds): EXAMPLES:: - sage: penta = polytopes.regular_polygon(5) - sage: outline = penta.projection().render_outline_2d() # optional - sage.plot - sage: outline._objects[0] # optional - sage.plot + 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 Line defined by 2 points """ wireframe = [] @@ -1291,11 +1291,11 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, EXAMPLES:: - sage: P1 = polytopes.small_rhombicuboctahedron() - sage: Image1 = P1.projection().tikz([1,3,5], 175, scale=4, output_type='TikzPicture') - sage: type(Image1) + 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: Image1 + sage: Image1 # optional - sage.rings.number_field \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -1312,14 +1312,14 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% \end{tikzpicture} \end{document} - sage: _ = Image1.tex('polytope-tikz1.tex') # not tested - sage: _ = Image1.png('polytope-tikz1.png') # not tested - sage: _ = Image1.pdf('polytope-tikz1.pdf') # not tested - sage: _ = Image1.svg('polytope-tikz1.svg') # not tested + 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: 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 \documentclass[tikz]{standalone} @@ -1354,10 +1354,12 @@ 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 = Polyhedron(vertices=[[-1, -1, 2], [-1, 2, -1], [2, -1, -1]]) sage: 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',facet_color='orange!95!black', opacity=0.7, vertex_color='yellow', axis=True, output_type='TikzPicture') + sage: Image3 = P3.projection().tikz([0.5, -1, -0.1], 55, scale=3, edge_color='blue!95!black', # optional - sage.plot + ....: facet_color='orange!95!black', opacity=0.7, + ....: vertex_color='yellow', axis=True, output_type='TikzPicture') sage: Image3 \documentclass[tikz]{standalone} \begin{document} @@ -1600,21 +1602,23 @@ def _tikz_2d_in_3d(self, view, angle, scale, edge_color, facet_color, 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, edge_color='blue!95!black', facet_color='orange', opacity=0.5, vertex_color='yellow', axis=True) - sage: print('\n'.join(Image.splitlines()[:4])) + sage: Image = P.projection()._tikz_2d_in_3d(view=[0.5, -1, -0.5], angle=55, scale=3, # optional - sage.plot + ....: edge_color='blue!95!black', facet_color='orange', + ....: opacity=0.5, vertex_color='yellow', axis=True) + sage: print('\n'.join(Image.splitlines()[:4])) # optional - sage.plot \begin{tikzpicture}% [x={(0.644647cm, -0.476559cm)}, y={(0.192276cm, 0.857859cm)}, z={(-0.739905cm, -0.192276cm)}, - sage: with open('polytope-tikz3.tex', 'w') as f: # not tested + sage: with open('polytope-tikz3.tex', 'w') as f: # not tested # optional - sage.plot ....: _ = f.write(Image) :: - sage: p = Polyhedron(vertices=[[1,0,0],[0,1,0],[0,0,1]]) + sage: p = Polyhedron(vertices=[[1, 0, 0], [0, 1, 0], [0, 0, 1]]) sage: proj = p.projection() - sage: Img = proj.tikz([1,1,1],130,axis=True, output_type='LatexExpr') - sage: print('\n'.join(Img.splitlines()[12:21])) + sage: Img = proj.tikz([1, 1, 1], 130, axis=True, output_type='LatexExpr') # optional - sage.plot + sage: print('\n'.join(Img.splitlines()[12:21])) # optional - sage.plot %% with the command: ._tikz_2d_in_3d and parameters: %% view = [1, 1, 1] %% angle = 130 @@ -1747,23 +1751,28 @@ def _tikz_3d_in_3d(self, view, angle, scale, edge_color, EXAMPLES:: - sage: P = polytopes.small_rhombicuboctahedron() - sage: Image = P.projection()._tikz_3d_in_3d([3,7,5], 100, scale=3, edge_color='blue', facet_color='orange', opacity=0.5, vertex_color='green', axis=True) - sage: type(Image) + sage: P = polytopes.small_rhombicuboctahedron() # optional - sage.rings.number_field + sage: Image = P.projection()._tikz_3d_in_3d([3, 7, 5], 100, scale=3, + ....: edge_color='blue', facet_color='orange', + ....: opacity=0.5, vertex_color='green', axis=True) + sage: type(Image) # optional - sage.rings.number_field sage: print('\n'.join(Image.splitlines()[:4])) \begin{tikzpicture}% [x={(-0.046385cm, 0.837431cm)}, y={(-0.243536cm, 0.519228cm)}, z={(0.968782cm, 0.170622cm)}, - sage: with open('polytope-tikz1.tex', 'w') as f: # not tested + sage: with open('polytope-tikz1.tex', 'w') as f: # not tested # optional - sage.rings.number_field ....: _ = f.write(Image) :: - sage: Associahedron = Polyhedron(vertices=[[1,0,1],[1,0,0],[1,1,0],[0,0,-1],[0,1,0],[-1,0,0],[0,1,1],[0,0,1],[0,-1,0]]).polar() - sage: ImageAsso = Associahedron.projection().tikz([-15,-755,-655], 116, scale=1, output_type='LatexExpr') - sage: print('\n'.join(ImageAsso.splitlines()[12:30])) + sage: Associahedron = Polyhedron(vertices=[[1, 0, 1], [1, 0, 0], [1, 1, 0], + ....: [0, 0, -1], [0, 1, 0], [-1, 0, 0], + ....: [0, 1, 1], [0, 0, 1], [0, -1, 0]]).polar() + sage: ImageAsso = Associahedron.projection().tikz([-15, -755, -655], 116, scale=1, # optional - sage.plot + ....: output_type='LatexExpr') + sage: print('\n'.join(ImageAsso.splitlines()[12:30])) # optional - sage.plot %% with the command: ._tikz_3d_in_3d and parameters: %% view = [-15, -755, -655] %% angle = 116 diff --git a/src/sage/numerical/all__sagemath_polyhedra.py b/src/sage/numerical/all__sagemath_polyhedra.py new file mode 100644 index 00000000000..6de2a9af502 --- /dev/null +++ b/src/sage/numerical/all__sagemath_polyhedra.py @@ -0,0 +1,9 @@ +from sage.misc.lazy_import import lazy_import + +lazy_import("sage.numerical.mip", ["MixedIntegerLinearProgram"]) +lazy_import("sage.numerical.sdp", ["SemidefiniteProgram"]) +lazy_import("sage.numerical.backends.generic_backend", ["default_mip_solver"]) +lazy_import("sage.numerical.backends.generic_sdp_backend", ["default_sdp_solver"]) + +lazy_import("sage.numerical.interactive_simplex_method", + ["InteractiveLPProblem", "InteractiveLPProblemStandardForm"]) diff --git a/src/sage/numerical/backends/all__sagemath_polyhedra.py b/src/sage/numerical/backends/all__sagemath_polyhedra.py new file mode 100644 index 00000000000..e69de29bb2d From f01367ad1034ce377598569f5a3cd4bf4d906957 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 27 Jan 2023 22:39:22 -0800 Subject: [PATCH 2/8] sage.geometry.polyhedron: More # optional --- src/sage/features/sagemath.py | 22 +++++++ src/sage/geometry/polyhedron/base.py | 24 +++---- src/sage/geometry/polyhedron/base6.py | 16 ++--- src/sage/geometry/polyhedron/base_QQ.py | 20 +++--- src/sage/geometry/polyhedron/constructor.py | 9 +-- src/sage/geometry/polyhedron/library.py | 62 +++++++++---------- src/sage/geometry/polyhedron/parent.py | 4 +- src/sage/geometry/polyhedron/plot.py | 35 +++++++---- .../polyhedron/ppl_lattice_polytope.py | 2 +- .../interfaces/all__sagemath_polyhedra.py | 0 .../numerical/backends/generic_backend.pyx | 3 +- 11 files changed, 115 insertions(+), 82 deletions(-) create mode 100644 src/sage/interfaces/all__sagemath_polyhedra.py diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index 58552614425..4085679dbd8 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -209,6 +209,27 @@ def __init__(self): PythonModule.__init__(self, 'sage.rings.real_double') +class sage__rings__real_mpfr(PythonModule): + r""" + A :class:`~sage.features.Feature` describing the presence of :mod:`sage.rings.real_mpfr`. + + EXAMPLES:: + + sage: from sage.features.sagemath import sage__rings__real_mpfr + sage: sage__rings__real_mpfr().is_present() # optional - sage.rings.real_mpfr + FeatureTestResult('sage.rings.real_mpfr', True) + """ + def __init__(self): + r""" + TESTS:: + + sage: from sage.features.sagemath import sage__rings__real_mpfr + sage: isinstance(sage__rings__real_mpfr(), sage__rings__real_mpfr) + True + """ + PythonModule.__init__(self, 'sage.rings.real_mpfr') + + class sage__symbolic(JoinFeature): r""" A :class:`~sage.features.Feature` describing the presence of :mod:`sage.symbolic`. @@ -263,4 +284,5 @@ def all_features(): sage__rings__number_field(), sage__rings__padics(), sage__rings__real_double(), + sage__rings__real_mpfr(), sage__symbolic()] diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 9704f6ea607..f28560bad05 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -623,7 +623,7 @@ def hyperplane_arrangement(self): EXAMPLES:: sage: p = polytopes.hypercube(2) - sage: p.hyperplane_arrangement() + 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())) @@ -966,16 +966,16 @@ def permutations_to_matrices(self, conj_class_reps, acting_group=None, additiona 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.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 - sage: conj_reps = aut_square.conjugacy_classes_representatives() # optional - pynormaliz - sage: gens_dict = square.permutations_to_matrices(conj_reps); # optional - pynormaliz - sage: rotation_180 = aut_square([(0,3),(1,2)]) # optional - pynormaliz - sage: rotation_180,gens_dict[rotation_180] # optional - pynormaliz + 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 ( [-1 0 0] [ 0 -1 0] @@ -985,11 +985,11 @@ 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') - sage: conj_reps = G.conjugacy_classes_representatives() - sage: add_elt = G([(0,2,3,1)]) - sage: dict = C.permutations_to_matrices(conj_reps,additional_elts = [add_elt]) - sage: dict[add_elt] + 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 [ 0 1 0] [-1 0 0] [ 0 0 1] diff --git a/src/sage/geometry/polyhedron/base6.py b/src/sage/geometry/polyhedron/base6.py index a279898247e..cf6ffe8f2a2 100644 --- a/src/sage/geometry/polyhedron/base6.py +++ b/src/sage/geometry/polyhedron/base6.py @@ -573,7 +573,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])) + 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); @@ -860,17 +860,17 @@ def schlegel_projection(self, facet=None, position=None): 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]) - sage: sp.plot() # optional - sage.plot + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4]) # optional - sage.symbolic + sage: sp.plot() # optional - sage.plot # optional - sage.symbolic Graphics3d Object A different values of ``position`` changes the projection:: - sage: sp = tfcube.schlegel_projection(tfcube.facets()[4],1/2) - sage: sp.plot() # optional - sage.plot + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 1/2) # optional - sage.symbolic + sage: sp.plot() # optional - sage.plot # optional - sage.symbolic Graphics3d Object - sage: sp = tfcube.schlegel_projection(tfcube.facets()[4],4) - sage: sp.plot() # optional - sage.plot + sage: sp = tfcube.schlegel_projection(tfcube.facets()[4], 4) # optional - sage.symbolic + sage: sp.plot() # optional - sage.plot # optional - sage.symbolic Graphics3d Object A value which is too large give a projection point that sees more than @@ -966,7 +966,7 @@ def _affine_hull_projection(self, *, sage: P = Polyhedron(V) sage: P.affine_hull_projection() A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 6 vertices - sage: P.affine_hull_projection(orthonormal=True) + 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" diff --git a/src/sage/geometry/polyhedron/base_QQ.py b/src/sage/geometry/polyhedron/base_QQ.py index 0efcb15f1a2..de26b9acbd9 100644 --- a/src/sage/geometry/polyhedron/base_QQ.py +++ b/src/sage/geometry/polyhedron/base_QQ.py @@ -150,12 +150,12 @@ def integral_points_count(self, verbose=False, use_Hrepresentation=False, "Fibonacci" knapsacks (preprocessing helps a lot):: - sage: def fibonacci_knapsack(d, b, backend=None): + sage: def fibonacci_knapsack(d, b, backend=None): # optional - sage.combinat ....: lp = MixedIntegerLinearProgram(base_ring=QQ) ....: x = lp.new_variable(nonnegative=True) ....: lp.add_constraint(lp.sum(fibonacci(i+3)*x[i] for i in range(d)) <= b) ....: return lp.polyhedron(backend=backend) - sage: fibonacci_knapsack(20, 12).integral_points_count() # does not finish with preprocess=False + sage: fibonacci_knapsack(20, 12).integral_points_count() # does not finish with preprocess=False # optional - sage.combinat 33 TESTS: @@ -931,20 +931,20 @@ def fixed_subpolytopes(self, conj_class_reps): 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 - sage: aut_p.order() # optional - pynormaliz + sage: aut_p = p.restricted_automorphism_group(output='permutation') # optional - pynormaliz # optional - sage.groups + sage: aut_p.order() # optional - pynormaliz # optional - sage.groups 8 - sage: conj_list = aut_p.conjugacy_classes_representatives(); # optional - pynormaliz - sage: fixedpolytopes_dictionary = p.fixed_subpolytopes(conj_list) # optional - pynormaliz - sage: fixedpolytopes_dictionary[aut_p([(0,3),(1,2)])] # optional - pynormaliz + 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 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') - sage: conj_list = aut_P.conjugacy_classes_representatives() - sage: P.fixed_subpolytopes(conj_list) + 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 diff --git a/src/sage/geometry/polyhedron/constructor.py b/src/sage/geometry/polyhedron/constructor.py index 971e36388f4..0a8cc1854ac 100644 --- a/src/sage/geometry/polyhedron/constructor.py +++ b/src/sage/geometry/polyhedron/constructor.py @@ -217,7 +217,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]]) + 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' @@ -563,18 +563,19 @@ 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), (6.4876921900819049, 4.8435898415984129)]) + sage: Polyhedron(vertices=[(8.3319544851638732, 7.0567045956967727), # optional - sage.rings.real_mpfr + ....: (6.4876921900819049, 4.8435898415984129)]) Traceback (most recent call last): ... ValueError: the only allowed inexact ring is 'RDF' with backend 'cdd' 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)) + 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)) + 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/library.py b/src/sage/geometry/polyhedron/library.py index f9fb4e192cd..f621f9329ff 100644 --- a/src/sage/geometry/polyhedron/library.py +++ b/src/sage/geometry/polyhedron/library.py @@ -724,18 +724,18 @@ def icosahedron(self, exact=True, base_ring=None, backend=None): Its non exact version:: - sage: ico = polytopes.icosahedron(exact=False) - sage: ico.base_ring() + 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) + 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 - sage: ico.base_ring() # long time # optional - sage.rings.number_field + 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 Algebraic Real Field - sage: ico.volume() # long time # optional - sage.rings.number_field + sage: ico.volume() # long time # optional - sage.rings.number_field # optional - sage.groups 2.181694990624913? Note that if base ring is provided it must contain the square root of @@ -748,15 +748,15 @@ def icosahedron(self, exact=True, base_ring=None, backend=None): TESTS:: - sage: ico = polytopes.icosahedron(backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field - sage: ico.f_vector() # optional - pynormaliz # optional - sage.rings.number_field + 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 (1, 12, 30, 20, 1) - sage: ico.volume() # optional - pynormaliz # optional - sage.rings.number_field + sage: ico.volume() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups 5/12*sqrt5 + 5/4 - sage: TestSuite(ico).run() # optional - pynormaliz # optional - sage.rings.number_field + sage: TestSuite(ico).run() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups - sage: ico = polytopes.icosahedron(exact=False) - sage: TestSuite(ico).run(skip="_test_lawrence") + 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 - sage: d12.f_vector() # optional - sage.rings.number_field + sage: d12 = polytopes.dodecahedron() # optional - sage.rings.number_field # optional - sage.groups + sage: d12.f_vector() # optional - sage.rings.number_field # optional - sage.groups (1, 20, 30, 12, 1) - sage: d12.volume() # optional - sage.rings.number_field + sage: d12.volume() # optional - sage.rings.number_field # optional - sage.groups -176*sqrt5 + 400 - sage: numerical_approx(_) # optional - sage.rings.number_field + sage: numerical_approx(_) # optional - sage.rings.number_field # optional - sage.groups 6.45203596003699 - sage: d12 = polytopes.dodecahedron(exact=False) - sage: d12.base_ring() + 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 + sage: polytopes.dodecahedron(base_ring=QQ) # optional - sage.symbolic # optional - 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 - sage: d12.f_vector() # optional - pynormaliz # optional - sage.rings.number_field + 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 (1, 20, 30, 12, 1) - sage: TestSuite(d12).run() # optional - pynormaliz # optional - sage.rings.number_field + sage: TestSuite(d12).run() # optional - pynormaliz # optional - sage.rings.number_field # optional - sage.groups """ return self.icosahedron(exact=exact, base_ring=base_ring, backend=backend).polar() @@ -1600,17 +1600,17 @@ def truncated_dodecahedron(self, exact=True, base_ring=None, backend=None): EXAMPLES:: - sage: td = polytopes.truncated_dodecahedron() - sage: td.f_vector() + 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() + 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) + 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) + 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 @@ -1633,10 +1633,10 @@ def truncated_dodecahedron(self, exact=True, base_ring=None, backend=None): TESTS:: - sage: td = polytopes.truncated_dodecahedron(backend='normaliz') # optional - pynormaliz - sage: td.f_vector() # optional - pynormaliz + 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 (1, 60, 90, 32, 1) - sage: td.base_ring() # optional - pynormaliz + 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? """ @@ -2604,7 +2604,7 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula 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 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) + 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 A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 12 vertices diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 8e2e868294d..352b2b1481e 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -96,11 +96,11 @@ def Polyhedra(ambient_space_or_base_ring=None, ambient_dim=None, backend=None, * TESTS:: - sage: Polyhedra(RR, 3, backend='field') + 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) + 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 diff --git a/src/sage/geometry/polyhedron/plot.py b/src/sage/geometry/polyhedron/plot.py index c53357404c6..c54b92116f3 100644 --- a/src/sage/geometry/polyhedron/plot.py +++ b/src/sage/geometry/polyhedron/plot.py @@ -13,7 +13,7 @@ from math import pi -from sage.rings.real_double import RDF +from sage.misc.lazy_import import lazy_import from sage.structure.sage_object import SageObject from sage.modules.free_module_element import vector from sage.matrix.constructor import matrix, identity_matrix @@ -22,7 +22,6 @@ from sage.misc.latex import LatexExpr from sage.structure.sequence import Sequence -from sage.misc.lazy_import import lazy_import lazy_import("sage.plot.all", ["Graphics", "point2d", "line2d", "arrow", "polygon2d", "rainbow"]) lazy_import("sage.plot.plot3d.all", ["point3d", "line3d", "arrow3d", "polygons3d"]) lazy_import("sage.plot.plot3d.transform", "rotate_arbitrary") @@ -178,6 +177,8 @@ def __init__(self, projection_point): [ 0.7071067811... 0.7071067811...] sage: TestSuite(proj).run(skip='_test_pickling') """ + from sage.rings.real_double import RDF + self.projection_point = vector(projection_point) self.dim = self.projection_point.degree() @@ -227,6 +228,8 @@ def __call__(self, x): sage: proj.__call__(vector([1,0,0])) (0.5, 0.0) """ + from sage.rings.real_double import RDF + img = self.house * x denom = self.psize - img[self.dim - 1] if denom.is_zero(): @@ -279,6 +282,8 @@ def __init__(self, facet, projection_point): (2.0, 2.0, 0.0) sage: TestSuite(proj).run(skip='_test_pickling') """ + from sage.rings.real_double import RDF + self.facet = facet ineq = [h for h in facet.ambient_Hrepresentation() if h.is_inequality()][0] self.full_A = ineq.A() @@ -500,14 +505,14 @@ def schlegel(self, facet=None, position=None): sage: tcube4 = cube4.face_truncation(cube4.faces(0)[0]) sage: tcube4.facets()[4] A 3-dimensional face of a Polyhedron in QQ^4 defined as the convex hull of 4 vertices - sage: into_tetra = Projection(tcube4).schlegel(tcube4.facets()[4]) - sage: into_tetra.plot() # optional - sage.plot + sage: into_tetra = Projection(tcube4).schlegel(tcube4.facets()[4]) # optional - sage.symbolic + sage: into_tetra.plot() # optional - sage.plot # optional - 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) - sage: into_tetra_far.plot() # optional - sage.plot + 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 Graphics3d Object A value which is too large or negative give a projection point that @@ -1360,7 +1365,7 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, sage: Image3 = P3.projection().tikz([0.5, -1, -0.1], 55, scale=3, edge_color='blue!95!black', # optional - sage.plot ....: facet_color='orange!95!black', opacity=0.7, ....: vertex_color='yellow', axis=True, output_type='TikzPicture') - sage: Image3 + sage: Image3 # optional - sage.plot \documentclass[tikz]{standalone} \begin{document} \begin{tikzpicture}% @@ -1377,10 +1382,10 @@ def tikz(self, view=[0, 0, 1], angle=0, scale=1, %% \end{tikzpicture} \end{document} - sage: _ = Image3.tex('polytope-tikz3.tex') # not tested - sage: _ = Image3.png('polytope-tikz3.png') # not tested - sage: _ = Image3.pdf('polytope-tikz3.pdf') # not tested - sage: _ = Image3.svg('polytope-tikz3.svg') # not tested + 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:: @@ -1633,6 +1638,8 @@ def _tikz_2d_in_3d(self, view, angle, scale, edge_color, facet_color, The ``facet_color`` is the filing color of the polytope (polygon). """ + from sage.rings.real_double import RDF + view_vector = vector(RDF, view) rot = rotate_arbitrary(view_vector, -(angle/360)*2*pi) rotation_matrix = rot[:2].transpose() @@ -1752,12 +1759,12 @@ def _tikz_3d_in_3d(self, view, angle, scale, edge_color, EXAMPLES:: sage: P = polytopes.small_rhombicuboctahedron() # optional - sage.rings.number_field - sage: Image = P.projection()._tikz_3d_in_3d([3, 7, 5], 100, scale=3, + sage: Image = P.projection()._tikz_3d_in_3d([3, 7, 5], 100, scale=3, # optional - sage.rings.number_field ....: edge_color='blue', facet_color='orange', ....: opacity=0.5, vertex_color='green', axis=True) sage: type(Image) # optional - sage.rings.number_field - sage: print('\n'.join(Image.splitlines()[:4])) + sage: print('\n'.join(Image.splitlines()[:4])) # optional - sage.rings.number_field \begin{tikzpicture}% [x={(-0.046385cm, 0.837431cm)}, y={(-0.243536cm, 0.519228cm)}, @@ -1792,6 +1799,8 @@ def _tikz_3d_in_3d(self, view, angle, scale, edge_color, \coordinate (1.00000, -1.00000, 0.00000) at (1.00000, -1.00000, 0.00000); \coordinate (1.00000, 0.00000, -1.00000) at (1.00000, 0.00000, -1.00000); """ + from sage.rings.real_double import RDF + view_vector = vector(RDF, view) rot = rotate_arbitrary(view_vector, -(angle/360)*2*pi) rotation_matrix = rot[:2].transpose() diff --git a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py index d45f8a3991a..895c7fed0c3 100644 --- a/src/sage/geometry/polyhedron/ppl_lattice_polytope.py +++ b/src/sage/geometry/polyhedron/ppl_lattice_polytope.py @@ -48,7 +48,7 @@ sage: square = LatticePolytope_PPL((-1,-1),(-1,1),(1,-1),(1,1)) sage: fibers = [ f.vertices() for f in square.fibration_generator(1) ]; fibers [((1, 0), (-1, 0)), ((0, 1), (0, -1)), ((-1, -1), (1, 1)), ((-1, 1), (1, -1))] - sage: square.pointsets_mod_automorphism(fibers) + sage: square.pointsets_mod_automorphism(fibers) # optional - sage.groups (frozenset({(-1, -1), (1, 1)}), frozenset({(-1, 0), (1, 0)})) AUTHORS: diff --git a/src/sage/interfaces/all__sagemath_polyhedra.py b/src/sage/interfaces/all__sagemath_polyhedra.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/sage/numerical/backends/generic_backend.pyx b/src/sage/numerical/backends/generic_backend.pyx index 64d47f7bc2b..18e73ff68af 100644 --- a/src/sage/numerical/backends/generic_backend.pyx +++ b/src/sage/numerical/backends/generic_backend.pyx @@ -1759,7 +1759,8 @@ cpdef GenericBackend get_solver(constraint_generation = False, solver = None, ba if base_ring is not None: base_ring = base_ring.fraction_field() - from sage.rings.all import QQ, RDF + from sage.rings.rational_field import QQ + from sage.rings.real_double import RDF if base_ring is QQ: solver = "Ppl" elif solver in ["Interactivelp", "Ppl"] and not base_ring.is_exact(): From 6fd026b7915ff579f55417485022f68ed32ba703 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Fri, 27 Jan 2023 23:19:28 -0800 Subject: [PATCH 3/8] sage.geometry: More # optional --- src/sage/geometry/cone_catalog.py | 16 ++-- .../hyperplane_arrangement/affine_subspace.py | 10 +-- .../hyperplane_arrangement/arrangement.py | 90 ++++++++++--------- src/sage/geometry/linear_expression.py | 2 +- 4 files changed, 62 insertions(+), 56 deletions(-) diff --git a/src/sage/geometry/cone_catalog.py b/src/sage/geometry/cone_catalog.py index a3d1ffa670f..185391d261a 100644 --- a/src/sage/geometry/cone_catalog.py +++ b/src/sage/geometry/cone_catalog.py @@ -374,8 +374,8 @@ def rearrangement(p, ambient_dim=None, lattice=None): sage: ambient_dim = ZZ.random_element(2,10).abs() sage: p = ZZ.random_element(1, ambient_dim) sage: K = cones.rearrangement(p, ambient_dim) - sage: P = SymmetricGroup(ambient_dim).random_element().matrix() - sage: all( K.contains(P*r) for r in K ) + sage: P = SymmetricGroup(ambient_dim).random_element().matrix() # optional - sage.groups + sage: all(K.contains(P*r) for r in K) # optional - sage.groups True The smallest ``p`` components of every element of the rearrangement @@ -529,11 +529,11 @@ def schur(ambient_dim=None, lattice=None): sage: P = cones.schur(5) sage: Q = cones.nonnegative_orthant(5) - sage: G = ( g.change_ring(QQbar).normalized() for g in P ) - sage: H = ( h.change_ring(QQbar).normalized() for h in Q ) - sage: actual = max(arccos(u.inner_product(v)) for u in G for v in H) - sage: expected = 3*pi/4 - sage: abs(actual - expected).n() < 1e-12 + sage: G = ( g.change_ring(QQbar).normalized() for g in P ) # optional - sage.rings.number_fields + sage: H = ( h.change_ring(QQbar).normalized() for h in Q ) # optional - sage.rings.number_fields + sage: actual = max(arccos(u.inner_product(v)) for u in G for v in H) # optional - sage.rings.number_fields + sage: expected = 3*pi/4 # optional - sage.rings.number_fields + sage: abs(actual - expected).n() < 1e-12 # optional - sage.rings.number_fields True The dual of the Schur cone is the "downward monotonic cone" @@ -566,7 +566,7 @@ def schur(ambient_dim=None, lattice=None): True sage: x = V.random_element() sage: y = V.random_element() - sage: majorized_by(x,y) == ( (y-x) in S ) + sage: majorized_by(x,y) == ( (y-x) in S ) # optional - sage.rings.number_fields True If a ``lattice`` was given, it is actually used:: diff --git a/src/sage/geometry/hyperplane_arrangement/affine_subspace.py b/src/sage/geometry/hyperplane_arrangement/affine_subspace.py index 7c1065553c4..3b024b6f419 100644 --- a/src/sage/geometry/hyperplane_arrangement/affine_subspace.py +++ b/src/sage/geometry/hyperplane_arrangement/affine_subspace.py @@ -33,8 +33,8 @@ True sage: c < b False - sage: A = AffineSubspace([8,38,21,250], VectorSpace(GF(19),4)) - sage: A + sage: A = AffineSubspace([8,38,21,250], VectorSpace(GF(19),4)) # optional - sage.libs.pari + sage: A # optional - sage.libs.pari Affine space p + W where: p = (8, 0, 2, 3) W = Vector space of dimension 4 over Finite Field of size 19 @@ -384,9 +384,9 @@ def intersection(self, other): [] sage: A.intersection(C).intersection(B) - sage: D = AffineSubspace([1,2,3], VectorSpace(GF(5),3)) - sage: E = AffineSubspace([3,4,5], VectorSpace(GF(5),3)) - sage: D.intersection(E) + sage: D = AffineSubspace([1,2,3], VectorSpace(GF(5),3)) # optional - sage.libs.pari + sage: E = AffineSubspace([3,4,5], VectorSpace(GF(5),3)) # optional - sage.libs.pari + sage: D.intersection(E) # optional - sage.libs.pari Affine space p + W where: p = (3, 4, 0) W = Vector space of dimension 3 over Finite Field of size 5 diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index 5b2534677a1..b2438ed284f 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -60,30 +60,30 @@ The default base field is `\QQ`, the rational numbers. Finite fields are also supported:: - sage: H. = HyperplaneArrangements(GF(5)) - sage: a = H([(1,2,3), 4], [(5,6,7), 8]); a + 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 Arrangement Number fields are also possible:: sage: x = var('x') - sage: NF. = NumberField(x**4 - 5*x**2 + 5,embedding=1.90) - sage: H. = HyperplaneArrangements(NF) - sage: A = H([[(-a**3 + 3*a, -a**2 + 4), 1], [(a**3 - 4*a, -1), 1], + 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 + sage: A # optional - sage.rings.number_field Arrangement of 5 hyperplanes of dimension 2 and rank 2 - sage: A.base_ring() + 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)) - sage: k = [x+i for i in range(4)]; k + sage: H. = HyperplaneArrangements(GF(5)) # optional - sage.libs.pari + sage: k = [x+i for i in range(4)]; k # optional - sage.libs.pari [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) + sage: H(k) # optional - sage.libs.pari Arrangement Notation (iv): using the library of arrangements:: @@ -264,10 +264,10 @@ sage: a = hyperplane_arrangements.semiorder(3) sage: a.has_good_reduction(5) True - sage: b = a.change_ring(GF(5)) + sage: b = a.change_ring(GF(5)) # optional - sage.libs.pari sage: pa = a.intersection_poset() - sage: pb = b.intersection_poset() - sage: pa.is_isomorphic(pb) + sage: pb = b.intersection_poset() # optional - sage.libs.pari + sage: pa.is_isomorphic(pb) # optional - sage.libs.pari True sage: a.face_vector() (0, 12, 30, 19) @@ -356,7 +356,6 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.geometry.hyperplane_arrangement.hyperplane import AmbientVectorSpace, Hyperplane -from sage.combinat.posets.posets import Poset class HyperplaneArrangementElement(Element): @@ -1129,7 +1128,7 @@ def change_ring(self, base_ring): sage: H. = HyperplaneArrangements(QQ) sage: A = H([(1,1), 0], [(2,3), -1]) - sage: A.change_ring(FiniteField(2)) + sage: A.change_ring(FiniteField(2)) # optional - sage.libs.pari Arrangement TESTS: @@ -1165,8 +1164,8 @@ def n_regions(self): sage: H. = HyperplaneArrangements(QQ) sage: A = H([(1,1), 0], [(2,3), -1], [(4,5), 3]) - sage: B = A.change_ring(FiniteField(7)) - sage: B.n_regions() + sage: B = A.change_ring(FiniteField(7)) # optional - sage.libs.pari + sage: B.n_regions() # optional - sage.libs.pari Traceback (most recent call last): ... TypeError: base field must have characteristic zero @@ -1174,16 +1173,21 @@ def n_regions(self): Check that :trac:`30749` is fixed:: sage: R. = QQ[] - sage: v1 = AA.polynomial_root(AA.common_polynomial(y^2 - 3), RIF(RR(1.7320508075688772), RR(1.7320508075688774))) - sage: v2 = QQbar.polynomial_root(AA.common_polynomial(y^4 - y^2 + 1), CIF(RIF(RR(0.8660254037844386), RR(0.86602540378443871)), RIF(-RR(0.50000000000000011), -RR(0.49999999999999994)))) - sage: my_vectors = (vector(AA, [-v1, -1, 1]), vector(AA, [0, 2, 1]), vector(AA,[v1, -1, 1]), vector(AA, [1, 0, 0]), vector(AA, [1/2, AA(-1/2*v2^3 + v2),0]), vector(AA, [-1/2, AA(-1/2*v2^3 + v2), 0])) - sage: H = HyperplaneArrangements(AA, names='xyz') - sage: x,y,z = H.gens() - sage: A = H(backend="normaliz") # optional - pynormaliz - sage: for v in my_vectors: # optional - pynormaliz + sage: v1 = AA.polynomial_root(AA.common_polynomial(y^2 - 3), # optional - sage.rings.number_field + ....: RIF(RR(1.7320508075688772), RR(1.7320508075688774))) + sage: v2 = QQbar.polynomial_root(AA.common_polynomial(y^4 - y^2 + 1), # optional - sage.rings.number_field + ....: CIF(RIF(RR(0.8660254037844386), RR(0.86602540378443871)), + ....: RIF(-RR(0.50000000000000011), -RR(0.49999999999999994)))) + sage: my_vectors = (vector(AA, [-v1, -1, 1]), vector(AA, [0, 2, 1]), vector(AA, [v1, -1, 1]), # optional - sage.rings.number_field + ....: vector(AA, [1, 0, 0]), vector(AA, [1/2, AA(-1/2*v2^3 + v2),0]), + ....: vector(AA, [-1/2, AA(-1/2*v2^3 + v2), 0])) + sage: H = HyperplaneArrangements(AA, names='xyz') # optional - sage.rings.number_field + sage: x,y,z = H.gens() # optional - sage.rings.number_field + sage: A = H(backend="normaliz") # optional - pynormaliz # optional - sage.rings.number_field + sage: for v in my_vectors: # optional - pynormaliz # optional - sage.rings.number_field ....: a, b, c = v ....: A = A.add_hyperplane(a*x + b*y + c*z) - sage: A.n_regions() # optional - pynormaliz + sage: A.n_regions() # optional - pynormaliz # optional - sage.rings.number_field 24 """ if self.base_ring().characteristic() != 0: @@ -1211,8 +1215,8 @@ def n_bounded_regions(self): sage: H. = HyperplaneArrangements(QQ) sage: A = H([(1,1),0], [(2,3),-1], [(4,5),3]) - sage: B = A.change_ring(FiniteField(7)) - sage: B.n_bounded_regions() + sage: B = A.change_ring(FiniteField(7)) # optional - sage.libs.pari + sage: B.n_bounded_regions() # optional - sage.libs.pari Traceback (most recent call last): ... TypeError: base field must have characteristic zero @@ -1243,14 +1247,14 @@ def has_good_reduction(self, p): EXAMPLES:: sage: a = hyperplane_arrangements.semiorder(3) - sage: a.has_good_reduction(5) + sage: a.has_good_reduction(5) # optional - sage.libs.pari True - sage: a.has_good_reduction(3) + sage: a.has_good_reduction(3) # optional - sage.libs.pari False - sage: b = a.change_ring(GF(3)) + sage: b = a.change_ring(GF(3)) # optional - sage.libs.pari sage: a.characteristic_polynomial() x^3 - 6*x^2 + 12*x - sage: b.characteristic_polynomial() # not equal to that for a + sage: b.characteristic_polynomial() # not equal to that for a # optional - sage.libs.pari x^3 - 6*x^2 + 10*x """ if self.base_ring() != QQ: @@ -1495,9 +1499,9 @@ def essentialization(self): Hyperplane arrangements in 1-dimensional linear space over Rational Field with coordinate x - sage: H. = HyperplaneArrangements(GF(2)) - sage: C = H([(1,1),1], [(1,1),0]) - sage: C.essentialization() + 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 Arrangement sage: h = hyperplane_arrangements.semiorder(4) @@ -1587,9 +1591,9 @@ def sign_vector(self, p): TESTS:: - sage: H. = HyperplaneArrangements(GF(3)) - sage: A = H(x, y) - sage: A.sign_vector([1, 2]) + 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 Traceback (most recent call last): ... ValueError: characteristic must be zero @@ -1992,6 +1996,8 @@ def poset_of_regions(self, B=None, numbered_labels=True): sage: A.poset_of_regions(B=base_region) Finite poset containing 14 elements """ + from sage.combinat.posets.posets import Poset + # We use RX to keep track of indexes and R to keep track of which regions # we've already hit. This poset is graded, so we can go one set at a time RX = self.regions() @@ -2480,7 +2486,7 @@ def face_semigroup_algebra(self, field=None, names='e'): sage: (e3 + 2*e4) * (e1 - e7) e4 - e6 - sage: U3 = a.face_semigroup_algebra(field=GF(3)); U3 + sage: U3 = a.face_semigroup_algebra(field=GF(3)); U3 # optional - sage.libs.pari Finite-dimensional algebra of degree 13 over Finite Field of size 3 TESTS: @@ -2550,8 +2556,8 @@ def region_containing_point(self, p): TESTS:: sage: A = H([(1,1),0], [(2,3),-1], [(4,5),3]) - sage: B = A.change_ring(FiniteField(7)) - sage: B.region_containing_point((1,2)) + sage: B = A.change_ring(FiniteField(7)) # optional - sage.libs.pari + sage: B.region_containing_point((1,2)) # optional - sage.libs.pari Traceback (most recent call last): ... ValueError: base field must have characteristic zero @@ -2991,8 +2997,8 @@ def matroid(self): intersection lattice:: sage: f = sum([list(M.flats(i)) for i in range(M.rank()+1)], []) - sage: PF = Poset([f, lambda x,y: x < y]) - sage: PF.is_isomorphic(A.intersection_poset()) + sage: PF = Poset([f, lambda x, y: x < y]) # optional - sage.combinat + sage: PF.is_isomorphic(A.intersection_poset()) # optional - sage.combinat True """ if not self.is_central(): diff --git a/src/sage/geometry/linear_expression.py b/src/sage/geometry/linear_expression.py index 7f4a91b3194..b62e17193a3 100644 --- a/src/sage/geometry/linear_expression.py +++ b/src/sage/geometry/linear_expression.py @@ -440,7 +440,7 @@ def evaluate(self, point): 9 sage: ex([1,1]) # syntactic sugar 9 - sage: ex([pi, e]) + sage: ex([pi, e]) # optional - sage.symbolic 2*pi + 3*e + 4 """ try: From 9400f51a2bda96c44fc1928b7de4dda13292daf3 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 26 Jan 2023 17:47:39 -0800 Subject: [PATCH 4/8] src/sage/rings/integer.pyx: Mark doctests # optional - sage.libs.pari, sage.rings.number_field, sage.symbolic --- src/sage/features/sagemath.py | 21 ++ src/sage/rings/integer.pyx | 372 +++++++++++++++++----------------- 2 files changed, 207 insertions(+), 186 deletions(-) diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index 4085679dbd8..fdcd07944e3 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -122,6 +122,27 @@ def __init__(self): [PythonModule('sage.groups.perm_gps.permgroup')]) +class sage__libs__pari(JoinFeature): + r""" + A :class:`sage.features.Feature` describing the presence of :mod:`sage.libs.pari`. + + EXAMPLES:: + + sage: from sage.features.sagemath import sage__libs__pari + sage: sage__libs__pari().is_present() # optional - sage.libs.pari + FeatureTestResult('sage.libs.pari', True) + """ + def __init__(self): + r""" + TESTS:: + + sage: from sage.features.sagemath import sage__libs__pari + sage: isinstance(sage__libs__pari(), sage__libs__pari) + True + """ + JoinFeature.__init__(self, 'sage.libs.pari', + [PythonModule('sage.libs.pari.convert_sage')]) + class sage__plot(JoinFeature): r""" A :class:`~sage.features.Feature` describing the presence of :mod:`sage.plot`. diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index c43319942fb..f038e747472 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -425,9 +425,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): Conversion from PARI:: - sage: Integer(pari('-10380104371593008048799446356441519384')) + sage: Integer(pari('-10380104371593008048799446356441519384')) # optional - sage.libs.pari -10380104371593008048799446356441519384 - sage: Integer(pari('Pol([-3])')) + sage: Integer(pari('Pol([-3])')) # optional - sage.libs.pari -3 Conversion from gmpy2:: @@ -463,11 +463,11 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): -901824309821093821093812093810928309183091832091 sage: ZZ(RR(2.0)^80) 1208925819614629174706176 - sage: ZZ(QQbar(sqrt(28-10*sqrt(3)) + sqrt(3))) + sage: ZZ(QQbar(sqrt(28-10*sqrt(3)) + sqrt(3))) # optional - sage.rings.number_field, sage.symbolic 5 - sage: ZZ(AA(32).nth_root(5)) + sage: ZZ(AA(32).nth_root(5)) # optional - sage.rings.number_field 2 - sage: ZZ(pari('Mod(-3,7)')) + sage: ZZ(pari('Mod(-3,7)')) # optional - sage.libs.pari 4 sage: ZZ('sage') Traceback (most recent call last): @@ -498,7 +498,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): :: - sage: k = GF(2) + sage: k = GF(2) # optional - sage.libs.pari sage: ZZ( (k(0),k(1)), 2) 2 @@ -535,40 +535,40 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): Test conversion from PARI (:trac:`11685`):: - sage: ZZ(pari(-3)) + sage: ZZ(pari(-3)) # optional - sage.libs.pari -3 - sage: ZZ(pari("-3.0")) + sage: ZZ(pari("-3.0")) # optional - sage.libs.pari -3 - sage: ZZ(pari("-3.5")) + sage: ZZ(pari("-3.5")) # optional - sage.libs.pari Traceback (most recent call last): ... TypeError: Attempt to coerce non-integral real number to an Integer - sage: ZZ(pari("1e100")) + sage: ZZ(pari("1e100")) # optional - sage.libs.pari Traceback (most recent call last): ... PariError: precision too low in truncr (precision loss in truncation) - sage: ZZ(pari("10^50")) + sage: ZZ(pari("10^50")) # optional - sage.libs.pari 100000000000000000000000000000000000000000000000000 - sage: ZZ(pari("Pol(3)")) + sage: ZZ(pari("Pol(3)")) # optional - sage.libs.pari 3 - sage: ZZ(GF(3^20,'t')(1)) + sage: ZZ(GF(3^20,'t')(1)) # optional - sage.libs.pari 1 - sage: ZZ(pari(GF(3^20,'t')(1))) + sage: ZZ(pari(GF(3^20,'t')(1))) # optional - sage.libs.pari 1 sage: x = polygen(QQ) - sage: K. = NumberField(x^2+3) - sage: ZZ(a^2) + sage: K. = NumberField(x^2+3) # optional - sage.rings.number_field + sage: ZZ(a^2) # optional - sage.rings.number_field -3 - sage: ZZ(pari(a)^2) + sage: ZZ(pari(a)^2) # optional - sage.libs.pari, sage.rings.number_field -3 - sage: ZZ(pari("Mod(x, x^3+x+1)")) # Note error message refers to lifted element + sage: ZZ(pari("Mod(x, x^3+x+1)")) # Note error message refers to lifted element # optional - sage.libs.pari Traceback (most recent call last): ... TypeError: Unable to coerce PARI x to an Integer Test coercion of p-adic with negative valuation:: - sage: ZZ(pari(Qp(11)(11^-7))) + sage: ZZ(pari(Qp(11)(11^-7))) # optional - sage.libs.pari Traceback (most recent call last): ... TypeError: Cannot convert p-adic with negative valuation to an integer @@ -769,8 +769,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: sage: n = -10 - sage: R = GF(17) - sage: n._im_gens_(R, [R(1)]) + sage: R = GF(17) # optional - sage.libs.pari + sage: n._im_gens_(R, [R(1)]) # optional - sage.libs.pari 7 """ return codomain.coerce(self) @@ -2008,7 +2008,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): Traceback (most recent call last): ... ZeroDivisionError: rational division by zero - sage: 3 / QQbar.zero() + sage: 3 / QQbar.zero() # optional - sage.rings.number_field Traceback (most recent call last): ... ZeroDivisionError: division by zero in algebraic field @@ -2113,7 +2113,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): 1 sage: 2^-0 1 - sage: (-1)^(1/3) + sage: (-1)^(1/3) # optional - sage.symbolic (-1)^(1/3) For consistency with Python and MPFR, 0^0 is defined to be 1 in @@ -2140,7 +2140,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): We raise 2 to various interesting exponents:: - sage: 2^x # symbolic x + sage: 2^x # symbolic x # optional - sage.symbolic 2^x sage: 2^1.5 # real number 2.82842712474619 @@ -2151,19 +2151,19 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: r = 2 ^ int(-3); r; type(r) 1/8 - sage: f = 2^(sin(x)-cos(x)); f + sage: f = 2^(sin(x)-cos(x)); f # optional - sage.symbolic 2^(-cos(x) + sin(x)) sage: f(x=3) 2^(-cos(3) + sin(3)) A symbolic sum:: - sage: x,y,z = var('x,y,z') - sage: 2^(x+y+z) + sage: x, y, z = var('x,y,z') # optional - sage.symbolic + sage: 2^(x + y + z) # optional - sage.symbolic 2^(x + y + z) - sage: 2^(1/2) + sage: 2^(1/2) # optional - sage.symbolic sqrt(2) - sage: 2^(-1/2) + sage: 2^(-1/2) # optional - sage.symbolic 1/2*sqrt(2) TESTS:: @@ -2767,13 +2767,13 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: Integer(124).log(5) + sage: Integer(124).log(5) # optional - sage.symbolic log(124)/log(5) - sage: Integer(124).log(5,100) + sage: Integer(124).log(5, 100) 2.9950093311241087454822446806 sage: Integer(125).log(5) 3 - sage: Integer(125).log(5,prec=53) + sage: Integer(125).log(5, prec=53) 3.00000000000000 sage: log(Integer(125)) 3*log(5) @@ -2781,7 +2781,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): For extremely large numbers, this works:: sage: x = 3^100000 - sage: log(x,3) + sage: log(x, 3) 100000 With the new Pynac symbolic backend, log(x) also @@ -2829,7 +2829,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): TESTS:: - sage: (-2).log(3) + sage: (-2).log(3) # optional - sage.symbolic (I*pi + log(2))/log(3) """ cdef int self_sgn @@ -2886,21 +2886,21 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: Integer(8).exp() + sage: Integer(8).exp() # optional - sage.symbolic e^8 - sage: Integer(8).exp(prec=100) + sage: Integer(8).exp(prec=100) # optional - sage.symbolic 2980.9579870417282747435920995 - sage: exp(Integer(8)) + sage: exp(Integer(8)) # optional - sage.symbolic e^8 For even fairly large numbers, this may not be useful. :: - sage: y=Integer(145^145) - sage: y.exp() + sage: y = Integer(145^145) + sage: y.exp() # optional - sage.symbolic e^25024207011349079210459585279553675697932183658421565260323592409432707306554163224876110094014450895759296242775250476115682350821522931225499163750010280453185147546962559031653355159703678703793369785727108337766011928747055351280379806937944746847277089168867282654496776717056860661614337004721164703369140625 - sage: y.exp(prec=53) # default RealField precision + sage: y.exp(prec=53) # default RealField precision # optional - sage.symbolic +infinity """ from sage.functions.all import exp @@ -3015,21 +3015,21 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): :: sage: n = 2^551 - 1 - sage: L = n.divisors() - sage: len(L) + sage: L = n.divisors() # optional - sage.libs.pari + sage: len(L) # optional - sage.libs.pari 256 - sage: L[-1] == n + sage: L[-1] == n # optional - sage.libs.pari True TESTS: Overflow:: - sage: prod(primes_first_n(64)).divisors() + sage: prod(primes_first_n(64)).divisors() # optional - sage.libs.pari Traceback (most recent call last): ... OverflowError: value too large - sage: prod(primes_first_n(58)).divisors() + sage: prod(primes_first_n(58)).divisors() # optional - sage.libs.pari Traceback (most recent call last): ... OverflowError: value too large # 32-bit @@ -3039,8 +3039,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): (the ``divisors`` call below allocates about 800 MB every time, so a memory leak will not go unnoticed):: - sage: n = prod(primes_first_n(25)) - sage: for i in range(20): # long time + sage: n = prod(primes_first_n(25)) # optional - sage.libs.pari + sage: for i in range(20): # long time # optional - sage.libs.pari ....: try: ....: alarm(RDF.random_element(1e-3, 0.5)) ....: _ = n.divisors() @@ -3322,9 +3322,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): This example caused trouble in :trac:`6083`:: - sage: a = next_prime(2**31) - sage: b = Integers(a)(100) - sage: a % b + sage: a = next_prime(2**31) # optional - sage.libs.pari + sage: b = Integers(a)(100) # optional - sage.libs.pari + sage: a % b # optional - sage.libs.pari Traceback (most recent call last): ... ArithmeticError: reduction modulo 100 not defined @@ -3678,26 +3678,26 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: n = next_prime(10^6)*next_prime(10^7); n.trial_division() + sage: n = next_prime(10^6)*next_prime(10^7); n.trial_division() # optional - sage.libs.pari 1000003 - sage: (-n).trial_division() + sage: (-n).trial_division() # optional - sage.libs.pari 1000003 - sage: n.trial_division(bound=100) + sage: n.trial_division(bound=100) # optional - sage.libs.pari 10000049000057 - sage: n.trial_division(bound=-10) + sage: n.trial_division(bound=-10) # optional - sage.libs.pari Traceback (most recent call last): ... ValueError: bound must be positive - sage: n.trial_division(bound=0) + sage: n.trial_division(bound=0) # optional - sage.libs.pari Traceback (most recent call last): ... ValueError: bound must be positive - sage: ZZ(0).trial_division() + sage: ZZ(0).trial_division() # optional - sage.libs.pari Traceback (most recent call last): ... ValueError: self must be nonzero - sage: n = next_prime(10^5) * next_prime(10^40); n.trial_division() + sage: n = next_prime(10^5) * next_prime(10^40); n.trial_division() # optional - sage.libs.pari 100003 sage: n.trial_division(bound=10^4) 1000030000000000000000000000000000000012100363 @@ -3705,17 +3705,17 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): 1000030000000000000000000000000000000012100363 sage: (-n).trial_division() 100003 - sage: n = 2 * next_prime(10^40); n.trial_division() + sage: n = 2 * next_prime(10^40); n.trial_division() # optional - sage.libs.pari 2 - sage: n = 3 * next_prime(10^40); n.trial_division() + sage: n = 3 * next_prime(10^40); n.trial_division() # optional - sage.libs.pari 3 - sage: n = 5 * next_prime(10^40); n.trial_division() + sage: n = 5 * next_prime(10^40); n.trial_division() # optional - sage.libs.pari 5 - sage: n = 2 * next_prime(10^4); n.trial_division() + sage: n = 2 * next_prime(10^4); n.trial_division() # optional - sage.libs.pari 2 - sage: n = 3 * next_prime(10^4); n.trial_division() + sage: n = 3 * next_prime(10^4); n.trial_division() # optional - sage.libs.pari 3 - sage: n = 5 * next_prime(10^4); n.trial_division() + sage: n = 5 * next_prime(10^4); n.trial_division() # optional - sage.libs.pari 5 You can specify a starting point:: @@ -3839,7 +3839,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: n = 2^100 - 1; n.factor() + sage: n = 2^100 - 1; n.factor() # optional - sage.libs.pari 3 * 5^3 * 11 * 31 * 41 * 101 * 251 * 601 * 1801 * 4051 * 8101 * 268501 This factorization can be converted into a list of pairs `(p, @@ -3866,9 +3866,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): that appear in the factorization:: sage: n = 920384092842390423848290348203948092384082349082 - sage: n.factor(proof=False) + sage: n.factor(proof=False) # optional - sage.libs.pari 2 * 11 * 1531 * 4402903 * 10023679 * 619162955472170540533894518173 - sage: n.factor(proof=True) + sage: n.factor(proof=True) # optional - sage.libs.pari 2 * 11 * 1531 * 4402903 * 10023679 * 619162955472170540533894518173 We factor using trial division only:: @@ -3878,10 +3878,10 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): We factor using a quadratic sieve algorithm:: - sage: p = next_prime(10^20) - sage: q = next_prime(10^21) - sage: n = p*q - sage: n.factor(algorithm='qsieve') + sage: p = next_prime(10^20) # optional - sage.libs.pari + sage: q = next_prime(10^21) # optional - sage.libs.pari + sage: n = p * q # optional - sage.libs.pari + sage: n.factor(algorithm='qsieve') # optional - sage.libs.pari doctest:... RuntimeWarning: the factorization returned by qsieve may be incomplete (the factors may not be prime) or even wrong; see qsieve? for details @@ -3889,10 +3889,10 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): We factor using the elliptic curve method:: - sage: p = next_prime(10^15) - sage: q = next_prime(10^21) - sage: n = p*q - sage: n.factor(algorithm='ecm') + sage: p = next_prime(10^15) # optional - sage.libs.pari + sage: q = next_prime(10^21) # optional - sage.libs.pari + sage: n = p * q # optional - sage.libs.pari + sage: n.factor(algorithm='ecm') # optional - sage.libs.pari 1000000000000037 * 1000000000000000000117 TESTS:: @@ -4776,23 +4776,23 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: 144.perfect_power() + sage: 144.perfect_power() # optional - sage.libs.pari (12, 2) - sage: 1.perfect_power() + sage: 1.perfect_power() # optional - sage.libs.pari (1, 1) - sage: 0.perfect_power() + sage: 0.perfect_power() # optional - sage.libs.pari (0, 1) - sage: (-1).perfect_power() + sage: (-1).perfect_power() # optional - sage.libs.pari (-1, 1) - sage: (-8).perfect_power() + sage: (-8).perfect_power() # optional - sage.libs.pari (-2, 3) - sage: (-4).perfect_power() + sage: (-4).perfect_power() # optional - sage.libs.pari (-4, 1) - sage: (101^29).perfect_power() + sage: (101^29).perfect_power() # optional - sage.libs.pari (101, 29) - sage: (-243).perfect_power() + sage: (-243).perfect_power() # optional - sage.libs.pari (-3, 5) - sage: (-64).perfect_power() + sage: (-64).perfect_power() # optional - sage.libs.pari (-4, 3) """ parians = self.__pari__().ispower() @@ -5079,55 +5079,55 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: 17.is_prime_power() + sage: 17.is_prime_power() # optional - sage.libs.pari True - sage: 10.is_prime_power() + sage: 10.is_prime_power() # optional - sage.libs.pari False - sage: 64.is_prime_power() + sage: 64.is_prime_power() # optional - sage.libs.pari True - sage: (3^10000).is_prime_power() + sage: (3^10000).is_prime_power() # optional - sage.libs.pari True - sage: (10000).is_prime_power() + sage: (10000).is_prime_power() # optional - sage.libs.pari False - sage: (-3).is_prime_power() + sage: (-3).is_prime_power() # optional - sage.libs.pari False - sage: 0.is_prime_power() + sage: 0.is_prime_power() # optional - sage.libs.pari False - sage: 1.is_prime_power() + sage: 1.is_prime_power() # optional - sage.libs.pari False - sage: p = next_prime(10^20); p + sage: p = next_prime(10^20); p # optional - sage.libs.pari 100000000000000000039 - sage: p.is_prime_power() + sage: p.is_prime_power() # optional - sage.libs.pari True - sage: (p^97).is_prime_power() + sage: (p^97).is_prime_power() # optional - sage.libs.pari True - sage: (p+1).is_prime_power() + sage: (p+1).is_prime_power() # optional - sage.libs.pari False With the ``get_data`` keyword set to ``True``:: - sage: (3^100).is_prime_power(get_data=True) + sage: (3^100).is_prime_power(get_data=True) # optional - sage.libs.pari (3, 100) - sage: 12.is_prime_power(get_data=True) + sage: 12.is_prime_power(get_data=True) # optional - sage.libs.pari (12, 0) - sage: (p^97).is_prime_power(get_data=True) + sage: (p^97).is_prime_power(get_data=True) # optional - sage.libs.pari (100000000000000000039, 97) - sage: q = p.next_prime(); q + sage: q = p.next_prime(); q # optional - sage.libs.pari 100000000000000000129 - sage: (p*q).is_prime_power(get_data=True) + sage: (p*q).is_prime_power(get_data=True) # optional - sage.libs.pari (10000000000000000016800000000000000005031, 0) The method works for large entries when `proof=False`:: sage: proof.arithmetic(False) - sage: ((10^500 + 961)^4).is_prime_power() + sage: ((10^500 + 961)^4).is_prime_power() # optional - sage.libs.pari True sage: proof.arithmetic(True) We check that :trac:`4777` is fixed:: sage: n = 150607571^14 - sage: n.is_prime_power() + sage: n.is_prime_power() # optional - sage.libs.pari True """ if mpz_sgn(self.value) <= 0: @@ -5201,26 +5201,26 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: sage: z = 2^31 - 1 - sage: z.is_prime() + sage: z.is_prime() # optional - sage.libs.pari True sage: z = 2^31 - sage: z.is_prime() + sage: z.is_prime() # optional - sage.libs.pari False sage: z = 7 - sage: z.is_prime() + sage: z.is_prime() # optional - sage.libs.pari True sage: z = -7 - sage: z.is_prime() + sage: z.is_prime() # optional - sage.libs.pari False - sage: z.is_irreducible() + sage: z.is_irreducible() # optional - sage.libs.pari True :: sage: z = 10^80 + 129 - sage: z.is_prime(proof=False) + sage: z.is_prime(proof=False) # optional - sage.libs.pari True - sage: z.is_prime(proof=True) + sage: z.is_prime(proof=True) # optional - sage.libs.pari True When starting Sage the arithmetic proof flag is True. We can change @@ -5229,12 +5229,12 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: proof.arithmetic() True sage: n = 10^100 + 267 - sage: timeit("n.is_prime()") # not tested + sage: timeit("n.is_prime()") # not tested # optional - sage.libs.pari 5 loops, best of 3: 163 ms per loop sage: proof.arithmetic(False) sage: proof.arithmetic() False - sage: timeit("n.is_prime()") # not tested + sage: timeit("n.is_prime()") # not tested # optional - sage.libs.pari 1000 loops, best of 3: 573 us per loop ALGORITHM: @@ -5251,7 +5251,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): ....: if tab[i]: ....: for j in range(2*i, size, i): ....: tab[j] = 0 - sage: all(ZZ(i).is_prime() == b for i,b in enumerate(tab)) + sage: all(ZZ(i).is_prime() == b for i,b in enumerate(tab)) # optional - sage.libs.pari True """ if mpz_sgn(self.value) <= 0: @@ -5314,16 +5314,16 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: sage: z = 2^31 - 1 - sage: z.is_irreducible() + sage: z.is_irreducible() # optional - sage.libs.pari True sage: z = 2^31 - sage: z.is_irreducible() + sage: z.is_irreducible() # optional - sage.libs.pari False sage: z = 7 - sage: z.is_irreducible() + sage: z.is_irreducible() # optional - sage.libs.pari True sage: z = -7 - sage: z.is_irreducible() + sage: z.is_irreducible() # optional - sage.libs.pari True """ cdef Integer n = self if self >= 0 else -self @@ -5343,10 +5343,10 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: sage: z = 2^31 - 1 - sage: z.is_pseudoprime() + sage: z.is_pseudoprime() # optional - sage.libs.pari True sage: z = 2^31 - sage: z.is_pseudoprime() + sage: z.is_pseudoprime() # optional - sage.libs.pari False """ return self.__pari__().ispseudoprime() @@ -5367,17 +5367,17 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: sage: x = 10^200 + 357 - sage: x.is_pseudoprime() + sage: x.is_pseudoprime() # optional - sage.libs.pari True - sage: (x^12).is_pseudoprime_power() + sage: (x^12).is_pseudoprime_power() # optional - sage.libs.pari True - sage: (x^12).is_pseudoprime_power(get_data=True) + sage: (x^12).is_pseudoprime_power(get_data=True) # optional - sage.libs.pari (1000...000357, 12) - sage: (997^100).is_pseudoprime_power() + sage: (997^100).is_pseudoprime_power() # optional - sage.libs.pari True - sage: (998^100).is_pseudoprime_power() + sage: (998^100).is_pseudoprime_power() # optional - sage.libs.pari False - sage: ((10^1000 + 453)^2).is_pseudoprime_power() + sage: ((10^1000 + 453)^2).is_pseudoprime_power() # optional - sage.libs.pari True TESTS:: @@ -5386,7 +5386,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): False sage: (-1).is_pseudoprime_power() False - sage: 1.is_pseudoprime_power() + sage: 1.is_pseudoprime_power() # optional - sage.libs.pari False """ return self.is_prime_power(proof=False, get_data=get_data) @@ -5453,20 +5453,20 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: K = NumberField(x^2 - 2, 'beta') + sage: K = NumberField(x^2 - 2, 'beta') # optional - sage.rings.number_field sage: n = 4 - sage: n.is_norm(K) + sage: n.is_norm(K) # optional - sage.rings.number_field True - sage: 5.is_norm(K) + sage: 5.is_norm(K) # optional - sage.rings.number_field False sage: 7.is_norm(QQ) True - sage: n.is_norm(K, element=True) + sage: n.is_norm(K, element=True) # optional - sage.rings.number_field (True, -4*beta + 6) - sage: n.is_norm(K, element=True)[1].norm() + sage: n.is_norm(K, element=True)[1].norm() # optional - sage.rings.number_field 4 sage: n = 5 - sage: n.is_norm(K, element=True) + sage: n.is_norm(K, element=True) # optional - sage.rings.number_field (False, None) sage: n = 7 sage: n.is_norm(QQ, element=True) @@ -5482,15 +5482,14 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: 3._bnfisnorm(QuadraticField(-1, 'i')) + sage: 3._bnfisnorm(QuadraticField(-1, 'i')) # optional - sage.rings.number_field (1, 3) - sage: 7._bnfisnorm(CyclotomicField(7)) + sage: 7._bnfisnorm(CyclotomicField(7)) # optional - sage.rings.number_field (zeta7^5 - zeta7^2, 1) """ from sage.rings.rational_field import QQ return QQ(self)._bnfisnorm(K, proof=proof, extra_primes=extra_primes) - def jacobi(self, b): r""" Calculate the Jacobi symbol `\left(\frac{self}{b}\right)`. @@ -5585,11 +5584,11 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: (-163).class_number() + sage: (-163).class_number() # optional - sage.libs.pari 1 - sage: (-104).class_number() + sage: (-104).class_number() # optional - sage.libs.pari 6 - sage: [((4*n+1),(4*n+1).class_number()) for n in [21..29]] + sage: [((4*n+1),(4*n+1).class_number()) for n in [21..29]] # optional - sage.libs.pari [(85, 2), (89, 1), (93, 1), @@ -5621,13 +5620,14 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): ... ValueError: class_number only defined for integers congruent to 0 or 1 modulo 4 """ - global objtogen - if objtogen is None: - from cypari2.gen import objtogen if self.is_square(): raise ValueError("class_number not defined for square integers") if self % 4 not in [0, 1]: raise ValueError("class_number only defined for integers congruent to 0 or 1 modulo 4") + + global objtogen + if objtogen is None: + from cypari2.gen import objtogen flag = self < 0 and proof return objtogen(self).qfbclassno(flag).sage() @@ -5670,8 +5670,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): 2 sage: a.squarefree_part(bound=2**14) 2 - sage: a = 7^3 * next_prime(2^100)^2 * next_prime(2^200) - sage: a / a.squarefree_part(bound=1000) + sage: a = 7^3 * next_prime(2^100)^2 * next_prime(2^200) # optional - sage.libs.pari + sage: a / a.squarefree_part(bound=1000) # optional - sage.libs.pari 49 """ cdef Integer z @@ -5718,17 +5718,17 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: (-37).next_probable_prime() + sage: (-37).next_probable_prime() # optional - sage.libs.pari 2 - sage: (100).next_probable_prime() + sage: (100).next_probable_prime() # optional - sage.libs.pari 101 - sage: (2^512).next_probable_prime() + sage: (2^512).next_probable_prime() # optional - sage.libs.pari 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084171 - sage: 0.next_probable_prime() + sage: 0.next_probable_prime() # optional - sage.libs.pari 2 - sage: 126.next_probable_prime() + sage: 126.next_probable_prime() # optional - sage.libs.pari 127 - sage: 144168.next_probable_prime() + sage: 144168.next_probable_prime() # optional - sage.libs.pari 144169 """ return Integer( self.__pari__().nextprime(True) ) @@ -5747,23 +5747,23 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: 100.next_prime() + sage: 100.next_prime() # optional - sage.libs.pari 101 - sage: (10^50).next_prime() + sage: (10^50).next_prime() # optional - sage.libs.pari 100000000000000000000000000000000000000000000000151 Use ``proof=False``, which is way faster since it does not need a primality proof:: - sage: b = (2^1024).next_prime(proof=False) - sage: b - 2^1024 + sage: b = (2^1024).next_prime(proof=False) # optional - sage.libs.pari + sage: b - 2^1024 # optional - sage.libs.pari 643 :: - sage: Integer(0).next_prime() + sage: Integer(0).next_prime() # optional - sage.libs.pari 2 - sage: Integer(1001).next_prime() + sage: Integer(1001).next_prime() # optional - sage.libs.pari 1009 """ # Use PARI to compute the next *pseudo*-prime @@ -5792,11 +5792,11 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: 10.previous_prime() + sage: 10.previous_prime() # optional - sage.libs.pari 7 - sage: 7.previous_prime() + sage: 7.previous_prime() # optional - sage.libs.pari 5 - sage: 14376485.previous_prime() + sage: 14376485.previous_prime() # optional - sage.libs.pari 14376463 sage: 2.previous_prime() @@ -5807,8 +5807,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): An example using ``proof=False``, which is way faster since it does not need a primality proof:: - sage: b = (2^1024).previous_prime(proof=False) - sage: 2^1024 - b + sage: b = (2^1024).previous_prime(proof=False) # optional - sage.libs.pari + sage: 2^1024 - b # optional - sage.libs.pari 105 """ if mpz_cmp_ui(self.value, 2) <= 0: @@ -5848,23 +5848,23 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: (-1).next_prime_power() 2 - sage: 2.next_prime_power() + sage: 2.next_prime_power() # optional - sage.libs.pari 3 - sage: 103.next_prime_power() + sage: 103.next_prime_power() # optional - sage.libs.pari 107 - sage: 107.next_prime_power() + sage: 107.next_prime_power() # optional - sage.libs.pari 109 - sage: 2044.next_prime_power() + sage: 2044.next_prime_power() # optional - sage.libs.pari 2048 TESTS:: - sage: [(2**k-1).next_prime_power() for k in range(1,10)] + sage: [(2**k-1).next_prime_power() for k in range(1,10)] # optional - sage.libs.pari [2, 4, 8, 16, 32, 64, 128, 256, 512] - sage: [(2**k).next_prime_power() for k in range(10)] + sage: [(2**k).next_prime_power() for k in range(10)] # optional - sage.libs.pari [2, 3, 5, 9, 17, 37, 67, 131, 257, 521] - sage: for _ in range(10): + sage: for _ in range(10): # optional - sage.libs.pari ....: n = ZZ.random_element(2**256).next_prime_power() ....: m = n.next_prime_power().previous_prime_power() ....: assert m == n, "problem with n = {}".format(n) @@ -5912,13 +5912,13 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: 3.previous_prime_power() + sage: 3.previous_prime_power() # optional - sage.libs.pari 2 - sage: 103.previous_prime_power() + sage: 103.previous_prime_power() # optional - sage.libs.pari 101 - sage: 107.previous_prime_power() + sage: 107.previous_prime_power() # optional - sage.libs.pari 103 - sage: 2044.previous_prime_power() + sage: 2044.previous_prime_power() # optional - sage.libs.pari 2039 sage: 2.previous_prime_power() @@ -5928,12 +5928,12 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): TESTS:: - sage: [(2**k+1).previous_prime_power() for k in range(1,10)] + sage: [(2**k+1).previous_prime_power() for k in range(1,10)] # optional - sage.libs.pari [2, 4, 8, 16, 32, 64, 128, 256, 512] - sage: [(2**k).previous_prime_power() for k in range(2, 10)] + sage: [(2**k).previous_prime_power() for k in range(2, 10)] # optional - sage.libs.pari [3, 7, 13, 31, 61, 127, 251, 509] - sage: for _ in range(10): + sage: for _ in range(10): # optional - sage.libs.pari ....: n = ZZ.random_element(3,2**256).previous_prime_power() ....: m = n.previous_prime_power().next_prime_power() ....: assert m == n, "problem with n = {}".format(n) @@ -6002,11 +6002,11 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: - sage: 100.is_squarefree() + sage: 100.is_squarefree() # optional - sage.libs.pari False - sage: 102.is_squarefree() + sage: 102.is_squarefree() # optional - sage.libs.pari True - sage: 0.is_squarefree() + sage: 0.is_squarefree() # optional - sage.libs.pari False """ return self.__pari__().issquarefree() @@ -6018,16 +6018,16 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): EXAMPLES:: sage: n = 9390823 - sage: m = n.__pari__(); m + sage: m = n.__pari__(); m # optional - sage.libs.pari 9390823 - sage: type(m) + sage: type(m) # optional - sage.libs.pari TESTS:: sage: n = 10^10000000 - sage: m = n.__pari__() # crash from trac 875 - sage: m % 1234567 + sage: m = n.__pari__() # crash from trac 875 # optional - sage.libs.pari + sage: m % 1234567 # optional - sage.libs.pari 1041334 """ @@ -6232,19 +6232,19 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): 12 sage: sqrt(Integer(144)) 12 - sage: Integer(102).sqrt() + sage: Integer(102).sqrt() # optional - sage.symbolic sqrt(102) :: sage: n = 2 - sage: n.sqrt(all=True) + sage: n.sqrt(all=True) # optional - sage.symbolic [sqrt(2), -sqrt(2)] sage: n.sqrt(prec=10) 1.4 sage: n.sqrt(prec=100) 1.4142135623730950488016887242 - sage: n.sqrt(prec=100,all=True) + sage: n.sqrt(prec=100, all=True) [1.4142135623730950488016887242, -1.4142135623730950488016887242] sage: n.sqrt(extend=False) Traceback (most recent call last): @@ -6261,7 +6261,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): TESTS:: - sage: type(5.sqrt()) + sage: type(5.sqrt()) # optional - sage.symbolic sage: type(5.sqrt(prec=53)) @@ -6887,7 +6887,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: 10.binomial(2) 45 - sage: 10.binomial(2, algorithm='pari') + sage: 10.binomial(2, algorithm='pari') # optional - sage.libs.pari 45 sage: 10.binomial(-2) 0 @@ -6929,7 +6929,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): check for reliable interrupting, see :trac:`18919`:: sage: from cysignals import AlarmInterrupt - sage: for i in [1..10]: # long time (5s) + sage: for i in [1..10]: # long time (5s) # optional - sage.libs.pari ....: try: ....: alarm(i/11) ....: (2^100).binomial(2^22, algorithm='pari') From a1d822dc93b0396b4a0407fe6132498a44270769 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 15 Feb 2023 13:20:53 -0800 Subject: [PATCH 5/8] src/sage/geometry/polyhedron/base2.py, src/sage/rings/integer.pyx: Reviewer fixes to # optional tags --- src/sage/geometry/polyhedron/base2.py | 4 ++-- src/sage/rings/integer.pyx | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/geometry/polyhedron/base2.py b/src/sage/geometry/polyhedron/base2.py index fa0765795cb..69d4204e29c 100644 --- a/src/sage/geometry/polyhedron/base2.py +++ b/src/sage/geometry/polyhedron/base2.py @@ -793,8 +793,8 @@ def generating_function_of_integral_points(self, **kwds): z^5 + z^6 + 2*z^7 + 3*z^8 + 5*z^9 + 7*z^10 + 10*z^11 + 13*z^12 + 18*z^13 + 23*z^14 + 30*z^15 + 37*z^16 + 47*z^17 + 57*z^18 + 70*z^19 + 84*z^20 + 101*z^21 + 119*z^22 + 141*z^23 + 164*z^24 + O(z^25) - sage: [Partitions(k, length=5).cardinality() for k in range(5,20)] == \ # optional - sage.combinat - ....: c.truncate().coefficients(sparse=False)[5:20] + sage: ([Partitions(k, length=5).cardinality() for k in range(5,20)] == # optional - sage.combinat + ....: c.truncate().coefficients(sparse=False)[5:20]) True .. SEEALSO:: diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index f038e747472..49fe893d5c8 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -499,7 +499,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): :: sage: k = GF(2) # optional - sage.libs.pari - sage: ZZ( (k(0),k(1)), 2) + sage: ZZ((k(0),k(1)), 2) # optional - sage.libs.pari 2 :: @@ -3699,11 +3699,11 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: n = next_prime(10^5) * next_prime(10^40); n.trial_division() # optional - sage.libs.pari 100003 - sage: n.trial_division(bound=10^4) + sage: n.trial_division(bound=10^4) # optional - sage.libs.pari 1000030000000000000000000000000000000012100363 - sage: (-n).trial_division(bound=10^4) + sage: (-n).trial_division(bound=10^4) # optional - sage.libs.pari 1000030000000000000000000000000000000012100363 - sage: (-n).trial_division() + sage: (-n).trial_division() # optional - sage.libs.pari 100003 sage: n = 2 * next_prime(10^40); n.trial_division() # optional - sage.libs.pari 2 From d6ffafd55a1275eb632133d05aeeea1620f88ece Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 15 Feb 2023 13:24:10 -0800 Subject: [PATCH 6/8] src/sage/features/sagemath.py (all_features): Add sage.libs.pari --- src/sage/features/sagemath.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index fdcd07944e3..3cb66162f07 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -143,6 +143,7 @@ def __init__(self): JoinFeature.__init__(self, 'sage.libs.pari', [PythonModule('sage.libs.pari.convert_sage')]) + class sage__plot(JoinFeature): r""" A :class:`~sage.features.Feature` describing the presence of :mod:`sage.plot`. @@ -301,6 +302,7 @@ def all_features(): sage__geometry__polyhedron(), sage__graphs(), sage__groups(), + sage__libs__pari(), sage__plot(), sage__rings__number_field(), sage__rings__padics(), From f7ec6a116705fb08506e02139f89bf2aabfc879d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Feb 2023 18:38:29 -0800 Subject: [PATCH 7/8] src/sage/geometry/polyhedral_complex.py: Mark # optional - sage.graphs --- src/sage/geometry/polyhedral_complex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/geometry/polyhedral_complex.py b/src/sage/geometry/polyhedral_complex.py index 913a788b5df..629a4f9ba2a 100644 --- a/src/sage/geometry/polyhedral_complex.py +++ b/src/sage/geometry/polyhedral_complex.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: optional - sage.graphs r""" Finite polyhedral complexes From 4aa626402d1f24565e151dc47ff3714a060fc8dd Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Thu, 16 Feb 2023 20:55:56 -0800 Subject: [PATCH 8/8] sage.geometry.triangulation: More # optional --- src/sage/geometry/triangulation/point_configuration.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index f970a5faf4a..3ad39184f37 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -1146,10 +1146,10 @@ 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() - sage: G == PermutationGroup([[(3,5)], [(2,3),(4,5)], [(2,4)]]) + 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) + sage: DihedralGroup(4).is_isomorphic(G) # optional - sage.graphs, sage.groups True The square with an off-center point in the middle. Note that @@ -1157,9 +1157,9 @@ def restricted_automorphism_group(self): `D_4` of the convex hull:: sage: square = PointConfiguration([(3/4,3/4),(1,1),(1,-1),(-1,-1),(-1,1)]) - sage: square.restricted_automorphism_group() + sage: square.restricted_automorphism_group() # optional - sage.graphs, sage.groups Permutation Group with generators [(3,5)] - sage: DihedralGroup(1).is_isomorphic(_) + sage: DihedralGroup(1).is_isomorphic(_) # optional - sage.graphs, sage.groups True """ v_list = [ vector(p.projective()) for p in self ]