From c7f12aaeb803e13be28ac080e4863f2f8b08eb2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 18 Dec 2025 17:51:54 +0100 Subject: [PATCH 1/3] create a monoid of lattice polytopes --- src/sage/geometry/lattice_polytope.py | 233 ++++++++++++++++---------- 1 file changed, 143 insertions(+), 90 deletions(-) diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 12136ad4ed6..35ac856e9d2 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -130,6 +130,7 @@ import shlex from sage.arith.misc import GCD as gcd +from sage.categories.monoids import Monoids from sage.features import PythonModule from sage.features.palp import PalpExecutable from sage.features.databases import DatabaseReflexivePolytopes @@ -147,11 +148,12 @@ from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.sets.set import Set_generic -from sage.structure.element import Matrix +from sage.structure.element import Matrix, Element from sage.structure.richcmp import richcmp_method, richcmp +from sage.structure.parent import Parent from sage.structure.sage_object import SageObject from sage.structure.sequence import Sequence +from sage.structure.unique_representation import UniqueRepresentation import sage.geometry.abc @@ -168,34 +170,6 @@ feature=PythonModule("ppl", spkg='pplpy', type='standard')) -class SetOfAllLatticePolytopesClass(Set_generic): - def _repr_(self) -> str: - r""" - Return a string representation. - - TESTS:: - - sage: lattice_polytope.SetOfAllLatticePolytopesClass()._repr_() - 'Set of all Lattice Polytopes' - """ - return "Set of all Lattice Polytopes" - - def __call__(self, x): - r""" - TESTS:: - - sage: o = lattice_polytope.cross_polytope(3) - sage: lattice_polytope.SetOfAllLatticePolytopesClass().__call__(o) - 3-d reflexive polytope in 3-d lattice M - """ - if isinstance(x, LatticePolytopeClass): - return x - raise TypeError - - -SetOfAllLatticePolytopes = SetOfAllLatticePolytopesClass() - - def LatticePolytope(data, compute_vertices=True, n=0, lattice=None): r""" Construct a lattice polytope. @@ -313,7 +287,7 @@ def LatticePolytope(data, compute_vertices=True, n=0, lattice=None): data = data._vertices compute_vertices = False if (isinstance(data, PointCollection) and - (lattice is None or lattice is data.module())): + (lattice is None or lattice is data.module())): return LatticePolytopeClass(data, compute_vertices) if isinstance(data, str): with open(data) as f: @@ -495,7 +469,8 @@ def is_LatticePolytope(x): @richcmp_method -class LatticePolytopeClass(ConvexSet_compact, Hashable, sage.geometry.abc.LatticePolytope): +class LatticePolytopeClass(Element, ConvexSet_compact, + sage.geometry.abc.LatticePolytope): r""" Create a lattice polytope. @@ -533,7 +508,6 @@ class LatticePolytopeClass(ConvexSet_compact, Hashable, sage.geometry.abc.Lattic Every polytope has an ambient structure. If it was not specified, it is this polytope itself. """ - def __init__(self, points=None, compute_vertices=None, ambient=None, ambient_vertex_indices=None, ambient_facet_indices=None) -> None: @@ -544,9 +518,12 @@ def __init__(self, points=None, compute_vertices=None, TESTS:: - sage: LatticePolytope([(1,2,3), (4,5,6)]) # indirect test + sage: P = LatticePolytope([(1,2,3), (4,5,6)]); P # indirect test 1-d lattice polytope in 3-d lattice M sage: TestSuite(_).run() + + sage: P.parent() + Set of all Lattice Polytopes """ if ambient is None: self._ambient = self @@ -569,6 +546,8 @@ def __init__(self, points=None, compute_vertices=None, self._ambient_vertex_indices = tuple(ambient_vertex_indices) self._ambient_facet_indices = tuple(ambient_facet_indices) self._vertices = ambient.vertices(self._ambient_vertex_indices) + parent = LatticePolytopes() + Element.__init__(self, parent) def _sage_input_(self, sib, coerced): """ @@ -589,7 +568,8 @@ def _sage_input_(self, sib, coerced): """ if self._ambient is not self: raise NotImplementedError - return sib.name('LatticePolytope')(sib(self._vertices), compute_vertices=False) + return sib.name('LatticePolytope')(sib(self._vertices), + compute_vertices=False) def __contains__(self, point) -> bool: r""" @@ -805,7 +785,7 @@ def _compute_facets(self): constants.append(Integer(c.inhomogeneous_term())) # Sort normals if facets are vertices if (self.dim() == 1 - and normals[0] * self.vertex(0) + constants[0] != 0): + and normals[0] * self.vertex(0) + constants[0] != 0): normals = (normals[1], normals[0]) constants = (constants[1], constants[0]) self._facet_normals = PointCollection(normals, N) @@ -1016,10 +996,8 @@ def _palp(self, command, reduce_dimension=False) -> str: result = f.read() os.remove(fn) if (not result or - "!" in result or - "failed." in result or - "increase" in result or - "Unable" in result): + "!" in result or "failed." in result or + "increase" in result or "Unable" in result): lines = ["Error executing '%s' for the given polytope!" % command, "Output:", result] raise ValueError("\n".join(lines)) @@ -1055,9 +1033,8 @@ def _PPL(self): -x0+x1-x2+1>=0, -x0+x1+x2+1>=0} """ - P = C_Polyhedron(Generator_System( - [PPL_point(Linear_Expression(v, 0)) for v in self.vertices()])) - return P + pts = [PPL_point(Linear_Expression(v, 0)) for v in self.vertices()] + return C_Polyhedron(Generator_System(pts)) def _pullback(self, data): r""" @@ -1210,7 +1187,7 @@ def _read_equations(self, data): self._facet_constants = vector(ZZ, constants) self._facet_constants.set_immutable() - def _read_nef_partitions(self, data): + def _read_nef_partitions(self, data) -> None: r""" Read nef-partitions of ``self`` from ``data``. @@ -1252,9 +1229,7 @@ def _read_nef_partitions(self, data): Nef-partition {0, 1, 2, 3} ⊔ {4, 5}] """ if isinstance(data, str): - f = StringIO(data) - self._read_nef_partitions(f) - f.close() + self._read_nef_partitions(StringIO(data)) return num_vertices = self.n_vertices() data.readline() # Skip M/N information @@ -1705,7 +1680,7 @@ def boundary_points(self): """ return self.points(self.boundary_point_indices()) - def contains(self, *args): + def contains(self, *args) -> bool: r""" Check if a given point is contained in ``self``. @@ -2034,12 +2009,12 @@ def LPFace(vertices, facets): from sage.graphs.digraph import DiGraph L = DiGraph() empty = self._ambient.face_lattice().bottom() - L.add_vertex(0) # In case it is the only one + L.add_vertex(0) # In case it is the only one dfaces = [empty] faces = [empty] - face_to_index = {empty:0} + face_to_index = {empty: 0} next_index = 1 - next_d = 0 # Dimension of faces to be considered next. + next_d = 0 # Dimension of faces to be considered next. while next_d < self.dim(): ndfaces = [] for face in dfaces: @@ -2602,7 +2577,7 @@ def is_reflexive(self): False """ return self.dim() == self.lattice_dim() and \ - all(c == 1 for c in self.facet_constants()) + all(c == 1 for c in self.facet_constants()) def lattice(self): r""" @@ -2790,7 +2765,7 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, """ if not self.is_reflexive(): raise ValueError(("The given polytope is not reflexive!\n" - + "Polytope: %s") % self) + + "Polytope: %s") % self) keys = "-N -V" if keep_symmetric: keys += " -s" @@ -2812,7 +2787,7 @@ def nef_partitions(self, keep_symmetric=False, keep_products=True, # Select only necessary partitions return Sequence([p for p in self._nef_partitions if (keep_projections or not p._is_projection) - and (keep_products or not p._is_product)], + and (keep_products or not p._is_product)], cr=True, check=False) self._read_nef_partitions(self.nef_x(keys)) self._npkeys = keys @@ -3207,7 +3182,7 @@ def _palp_modified_normal_form(self, permutation=False): PM_max = PM.permutation_normal_form() perm = PM.is_permutation_of(PM_max, check=True)[1] permutations = PM.automorphisms_of_rows_and_columns() - permutations = {k:[(perm[0])*p[0], (perm[1])*p[1]] + permutations = {k: [(perm[0])*p[0], (perm[1])*p[1]] for k, p in enumerate(permutations)} out = _palp_canonical_order(self.vertices(), PM_max, permutations) if permutation: @@ -3424,28 +3399,16 @@ def origin(self): except ValueError: pass - def parent(self): - """ - Return the set of all lattice polytopes. - - EXAMPLES:: - - sage: o = lattice_polytope.cross_polytope(3) - sage: o.parent() - Set of all Lattice Polytopes - """ - return SetOfAllLatticePolytopes - def plot3d(self, - show_facets=True, facet_opacity=0.5, facet_color=(0,1,0), - facet_colors=None, - show_edges=True, edge_thickness=3, edge_color=(0.5,0.5,0.5), - show_vertices=True, vertex_size=10, vertex_color=(1,0,0), - show_points=True, point_size=10, point_color=(0,0,1), - show_vindices=None, vindex_color=(0,0,0), - vlabels=None, - show_pindices=None, pindex_color=(0,0,0), - index_shift=1.1): + show_facets=True, facet_opacity=0.5, facet_color=(0, 1, 0), + facet_colors=None, + show_edges=True, edge_thickness=3, edge_color=(0.5, 0.5, 0.5), + show_vertices=True, vertex_size=10, vertex_color=(1, 0, 0), + show_points=True, point_size=10, point_color=(0, 0, 1), + show_vindices=None, vindex_color=(0, 0, 0), + vlabels=None, + show_pindices=None, pindex_color=(0, 0, 0), + index_shift=1.1): r""" Return a 3d-plot of this polytope. @@ -3841,9 +3804,27 @@ def polar(self): """ if self.is_reflexive(): return self._polar - else: - raise ValueError(("The given polytope is not reflexive!\n" - + "Polytope: %s") % self) + raise ValueError("The given polytope is not reflexive!\n" + f"Polytope: {self}") + + def _mul_(self, other): + """ + Return the direct product of two lattice polytopes. + + The dimension is the sum of the dimensions. + + EXAMPLES:: + + sage: P = lattice_polytope.cross_polytope(2) + sage: P*P + 4-d reflexive polytope in 4-d lattice M + """ + points1 = self._vertices + points2 = other._vertices + points = [p1.concatenate(p2) for p1 in points1 for p2 in points2] + P = LatticePolytope(points) + P.is_reflexive.set_cache(self.is_reflexive() and other.is_reflexive()) + return P def poly_x(self, keys, reduce_dimension=False): r""" @@ -4007,7 +3988,7 @@ def skeleton_show(self, normal=None): if self.lattice_dim() != 3: raise NotImplementedError("skeleton view is implemented only in 3-d space") if normal is None: - normal = [ZZ.random_element(20),ZZ.random_element(20),ZZ.random_element(20)] + normal = [ZZ.random_element(20) for _ in range(3)] normal = matrix(QQ, 3, 1, list(normal)) projectionm = normal.kernel().basis_matrix() positions = dict(enumerate([list(c) for c in (projectionm*self.points()).columns(copy=False)])) @@ -5440,7 +5421,7 @@ def all_polars(polytopes): This functions does it MUCH faster than member functions of ``LatticePolytope`` during the first run. So it is recommended to - use this functions if you work with big sets of data. + use this function if you work with big sets of data. INPUT: @@ -5488,7 +5469,7 @@ def convex_hull(points): sage: lattice_polytope.convex_hull([[1,2],[3,4],[5,6],[7,8]]) [(1, 2), (7, 8)] """ - if len(points) == 0: + if not points: return [] vpoints = [] for p in points: @@ -5501,14 +5482,13 @@ def convex_hull(points): H = N.submodule(vpoints) if H.rank() == 0: return [p0] - elif H.rank() == N.rank(): + if H.rank() == N.rank(): vpoints = list(LatticePolytope(vpoints, lattice=N).vertices()) else: H_points = [H.coordinates(p) for p in vpoints] H_polytope = LatticePolytope(H_points) vpoints = (H_polytope.vertices() * H.basis_matrix()).rows(copy=False) - vpoints = [p + p0 for p in vpoints] - return vpoints + return [p + p0 for p in vpoints] def cross_polytope(dim): @@ -5738,7 +5718,7 @@ def read_palp_matrix(data, permutation=False): [1 3 5] [2 4 6] """ - if isinstance(data,str): + if isinstance(data, str): f = StringIO(data) mat = read_palp_matrix(f, permutation=permutation) f.close() @@ -5753,7 +5733,7 @@ def read_palp_matrix(data, permutation=False): seq = [] for i in range(m): seq.extend(int(el) for el in data.readline().split()) - mat = matrix(ZZ,m,n,seq) + mat = matrix(ZZ, m, n, seq) if m > n: mat = mat.transpose() # In some cases there may be additional information to extract @@ -5905,17 +5885,90 @@ def write_palp_matrix(m, ofile=None, comment='', format=None): if isinstance(m, PointCollection): m = m.column_matrix() if format is None: - n = max(len(str(m[i,j])) + n = max(len(str(m[i, j])) for i in range(m.nrows()) for j in range(m.ncols())) format = "%" + str(n) + "d" - s = "%d %d %s\n" % (m.nrows(),m.ncols(),comment) + s = "%d %d %s\n" % (m.nrows(), m.ncols(), comment) if ofile is None: print(s, end=" ") else: ofile.write(s) for i in range(m.nrows()): - s = " ".join(format % m[i,j] for j in range(m.ncols()))+"\n" + s = " ".join(format % m[i, j] for j in range(m.ncols()))+"\n" if ofile is None: print(s, end=" ") else: ofile.write(s) + + +class LatticePolytopes(UniqueRepresentation, Parent): + """ + The set of all lattice polytopes. + + TESTS:: + + sage: o = lattice_polytope.cross_polytope(3) + sage: S = o.parent(); S + Set of all Lattice Polytopes + sage: S.cardinality() + +Infinity + """ + def __init__(self) -> None: + """ + The set of all lattice polytopes, as an infinite monoid. + + EXAMPLES:: + + sage: S = lattice_polytope.LatticePolytopes(); S + Set of all Lattice Polytopes + sage: S.category() + Category of infinite monoids + """ + Parent.__init__(self, category=Monoids().Infinite()) + + def _repr_(self) -> str: + r""" + Return a string representation. + + TESTS:: + + sage: lattice_polytope.LatticePolytopes() + Set of all Lattice Polytopes + """ + return "Set of all Lattice Polytopes" + + def one(self): + """ + Return the unit of the monoid. + + This is the point in dimension zero. + + EXAMPLES:: + + sage: lattice_polytope.LatticePolytopes().one() + 0-d reflexive polytope in 0-d lattice M + """ + return LatticePolytope([0], lattice=ToricLattice(0).dual()) + + def _element_constructor_(self, *data, **args): + r""" + EXAMPLES:: + + sage: o = lattice_polytope.cross_polytope(3) + sage: lattice_polytope.LatticePolytopes()(o) + 3-d reflexive polytope in 3-d lattice M + """ + return self.element_class(self, *data, **args) + + def _an_element_(self): + """ + Return an element. + + EXAMPLES:: + + sage: lattice_polytope.LatticePolytopes().an_element() + 2-d reflexive polytope #3 in 2-d lattice M + """ + return cross_polytope(2) + + Element = LatticePolytopeClass From ff949d02d8271521f6637785af279a54cb615622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 19 Dec 2025 20:49:52 +0100 Subject: [PATCH 2/3] use SetsWithGrading --- src/sage/geometry/lattice_polytope.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 35ac856e9d2..036d0426d21 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -131,6 +131,7 @@ from sage.arith.misc import GCD as gcd from sage.categories.monoids import Monoids +from sage.categories.sets_with_grading import SetsWithGrading from sage.features import PythonModule from sage.features.palp import PalpExecutable from sage.features.databases import DatabaseReflexivePolytopes @@ -1736,6 +1737,8 @@ def dim(self): nv = self.n_vertices() return self._PPL().affine_dimension() if nv > 3 else nv - 1 + grade = dim # for the category SetsWithGrading + def distances(self, point=None): r""" Return the matrix of distances for this polytope or distances for @@ -5922,9 +5925,11 @@ def __init__(self) -> None: sage: S = lattice_polytope.LatticePolytopes(); S Set of all Lattice Polytopes sage: S.category() - Category of infinite monoids + Join of Category of monoids and Category of sets with grading + and Category of infinite sets """ - Parent.__init__(self, category=Monoids().Infinite()) + cat = Monoids().Infinite() & SetsWithGrading() + Parent.__init__(self, category=cat) def _repr_(self) -> str: r""" From 7dfe9c69167570219987c181208d04985f9b8dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 21 Dec 2025 11:34:35 +0100 Subject: [PATCH 3/3] simpler but still not working --- src/sage/geometry/lattice_polytope.py | 59 +++++++++++---------------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 036d0426d21..a0bd26e91d3 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -131,7 +131,6 @@ from sage.arith.misc import GCD as gcd from sage.categories.monoids import Monoids -from sage.categories.sets_with_grading import SetsWithGrading from sage.features import PythonModule from sage.features.palp import PalpExecutable from sage.features.databases import DatabaseReflexivePolytopes @@ -284,12 +283,13 @@ def LatticePolytope(data, compute_vertices=True, n=0, lattice=None): sage: p.faces() # needs sage.graphs ((-1-d lattice polytope in 3-d lattice M,),) """ + parent = LatticePolytopes() if isinstance(data, LatticePolytopeClass): data = data._vertices compute_vertices = False if (isinstance(data, PointCollection) and (lattice is None or lattice is data.module())): - return LatticePolytopeClass(data, compute_vertices) + return LatticePolytopeClass(parent, data, compute_vertices) if isinstance(data, str): with open(data) as f: skip_palp_matrix(f, n) @@ -322,7 +322,7 @@ def LatticePolytope(data, compute_vertices=True, n=0, lattice=None): for p in data: p.set_immutable() data = PointCollection(data, lattice) - return LatticePolytopeClass(data, compute_vertices) + return LatticePolytopeClass(parent, data, compute_vertices) copyreg_constructor(LatticePolytope) # "safe for unpickling" @@ -509,7 +509,7 @@ class LatticePolytopeClass(Element, ConvexSet_compact, Every polytope has an ambient structure. If it was not specified, it is this polytope itself. """ - def __init__(self, points=None, compute_vertices=None, + def __init__(self, parent, points=None, compute_vertices=None, ambient=None, ambient_vertex_indices=None, ambient_facet_indices=None) -> None: r""" @@ -521,7 +521,7 @@ def __init__(self, points=None, compute_vertices=None, sage: P = LatticePolytope([(1,2,3), (4,5,6)]); P # indirect test 1-d lattice polytope in 3-d lattice M - sage: TestSuite(_).run() + sage: TestSuite(P).run() sage: P.parent() Set of all Lattice Polytopes @@ -547,7 +547,6 @@ def __init__(self, points=None, compute_vertices=None, self._ambient_vertex_indices = tuple(ambient_vertex_indices) self._ambient_facet_indices = tuple(ambient_facet_indices) self._vertices = ambient.vertices(self._ambient_vertex_indices) - parent = LatticePolytopes() Element.__init__(self, parent) def _sage_input_(self, sib, coerced): @@ -1269,7 +1268,7 @@ def _read_nef_partitions(self, data) -> None: partitions.set_immutable() self._nef_partitions = partitions - def _repr_(self): + def _repr_(self) -> str: r""" Return a string representation of ``self``. @@ -1299,7 +1298,7 @@ def _repr_(self): parts.extend(["face of", str(self.ambient())]) return " ".join(parts) - def _sort_faces(self, faces): + def _sort_faces(self, faces) -> tuple: r""" Return sorted (if necessary) ``faces`` as a tuple. @@ -1458,7 +1457,7 @@ def affine_transform(self, a=1, b=0): """ new_vertices = self.vertices() * a if b in QQ: - b = vector(QQ, [b]*new_vertices.ncols()) + b = vector(QQ, [b] * new_vertices.ncols()) else: b = vector(QQ, b) new_vertices = [c + b for c in new_vertices] @@ -1532,7 +1531,7 @@ def ambient_facet_indices(self): return self._ambient_facet_indices @cached_method - def ambient_point_indices(self): + def ambient_point_indices(self) -> tuple: r""" Return indices of points of the ambient polytope contained in this one. @@ -1557,7 +1556,7 @@ def ambient_point_indices(self): return tuple(point_to_index[p] for p in self.points()) @cached_method - def ambient_ordered_point_indices(self): + def ambient_ordered_point_indices(self) -> tuple: r""" Return indices of points of the ambient polytope contained in this one. @@ -1737,8 +1736,6 @@ def dim(self): nv = self.n_vertices() return self._PPL().affine_dimension() if nv > 3 else nv - 1 - grade = dim # for the category SetsWithGrading - def distances(self, point=None): r""" Return the matrix of distances for this polytope or distances for @@ -1990,6 +1987,7 @@ def face_lattice(self): sage: p.face_lattice().top() is p True """ + parent = self.parent() if self._ambient is self: # We need to compute face lattice on our own. vertex_to_facets = [row.nonzero_positions() @@ -2000,7 +1998,7 @@ def face_lattice(self): def LPFace(vertices, facets): if not facets: return self - return LatticePolytopeClass(ambient=self, + return LatticePolytopeClass(parent, ambient=self, ambient_vertex_indices=vertices, ambient_facet_indices=facets) @@ -2024,7 +2022,7 @@ def LPFace(vertices, facets): face_index = face_to_index[face] for new_face in face.facet_of(): if not allowed_indices.issuperset( - new_face._ambient_vertex_indices): + new_face._ambient_vertex_indices): continue if new_face in ndfaces: new_face_index = face_to_index[new_face] @@ -2126,7 +2124,7 @@ def faces(self, dim=None, codim=None): """ if dim is not None and codim is not None: raise ValueError( - "dimension and codimension cannot be specified together!") + "dimension and codimension cannot be specified together!") dim = self.dim() - codim if codim is not None else dim if "_faces" not in self.__dict__: self._faces = tuple(map(self._sort_faces, @@ -2417,7 +2415,7 @@ def incidence_matrix(self): for Hindex, normal in enumerate(self.facet_normals()): facet_constant = self.facet_constant(Hindex) for Vindex, vertex in enumerate(self.vertices()): - if normal*vertex + facet_constant == 0: + if normal * vertex + facet_constant == 0: incidence_matrix[Vindex, Hindex] = 1 incidence_matrix.set_immutable() @@ -3534,7 +3532,8 @@ def plot3d(self, if show_facets: if dim == 2: pplot += IndexFaceSet([self.traverse_boundary()], - vertices, opacity=facet_opacity, rgbcolor=facet_color) + vertices, opacity=facet_opacity, + rgbcolor=facet_color) elif dim == 3: if facet_colors is None: facet_colors = [facet_color] * self.n_facets() @@ -3549,7 +3548,8 @@ def plot3d(self, for e in self.edges(): start, end = e.ambient_vertex_indices() pplot += line3d([vertices[start], vertices[end]], - thickness=edge_thickness, rgbcolor=edge_color) + thickness=edge_thickness, + rgbcolor=edge_color) if show_vertices: pplot += point3d(vertices, size=vertex_size, rgbcolor=vertex_color) if show_vindices is None: @@ -4069,11 +4069,12 @@ def vertex_facet_pairing_matrix(self): V = self.vertices() nv = self.n_vertices() PM = matrix(ZZ, [n * V + vector(ZZ, [c] * nv) - for n, c in zip(self.facet_normals(), self.facet_constants())]) + for n, c in zip(self.facet_normals(), + self.facet_constants())]) PM.set_immutable() return PM - def vertices(self, *args, **kwds): + def vertices(self, *args, **kwds) -> PointCollection: r""" Return vertices of ``self``. @@ -5925,11 +5926,9 @@ def __init__(self) -> None: sage: S = lattice_polytope.LatticePolytopes(); S Set of all Lattice Polytopes sage: S.category() - Join of Category of monoids and Category of sets with grading - and Category of infinite sets + Category of infinite monoids """ - cat = Monoids().Infinite() & SetsWithGrading() - Parent.__init__(self, category=cat) + Parent.__init__(self, category=Monoids().Infinite()) def _repr_(self) -> str: r""" @@ -5955,16 +5954,6 @@ def one(self): """ return LatticePolytope([0], lattice=ToricLattice(0).dual()) - def _element_constructor_(self, *data, **args): - r""" - EXAMPLES:: - - sage: o = lattice_polytope.cross_polytope(3) - sage: lattice_polytope.LatticePolytopes()(o) - 3-d reflexive polytope in 3-d lattice M - """ - return self.element_class(self, *data, **args) - def _an_element_(self): """ Return an element.