From d38e1300355722815880dbd633863dd4d1b54173 Mon Sep 17 00:00:00 2001 From: Jonathan Kliem Date: Tue, 7 May 2019 17:33:25 +0200 Subject: [PATCH] added combinatorial face finished documentation of combinatorial_face --- src/module_list.py | 3 + .../combinatorial_polyhedron/base.pxd | 35 +- .../combinatorial_polyhedron/base.pyx | 612 +++++++---------- .../bit_vector_operations.cc | 48 +- .../bit_vector_operations.pxd | 24 +- .../combinatorial_face.pxd | 29 + .../combinatorial_face.pyx | 564 ++++++++++++++++ .../combinatorial_polyhedron/conversions.pxd | 4 +- .../combinatorial_polyhedron/conversions.pyx | 225 +++--- .../face_iterator.pxd | 19 +- .../face_iterator.pyx | 639 +++++++----------- .../list_of_all_faces.pxd | 10 +- .../list_of_all_faces.pyx | 255 ++----- .../list_of_faces.pxd | 6 +- .../list_of_faces.pyx | 74 +- 15 files changed, 1381 insertions(+), 1166 deletions(-) create mode 100644 src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd create mode 100644 src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx diff --git a/src/module_list.py b/src/module_list.py index 84ab2503bf1..e853749d45f 100644 --- a/src/module_list.py +++ b/src/module_list.py @@ -308,6 +308,9 @@ def uname_specific(name, value, alternative): Extension('sage.geometry.polyhedron.combinatorial_polyhedron.list_of_all_faces', sources = ['sage/geometry/polyhedron/combinatorial_polyhedron/list_of_all_faces.pyx']), + Extension('sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face', + sources = ['sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx']), + Extension('sage.geometry.polyhedron.combinatorial_polyhedron.conversions', sources = ['sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx']), diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd index 9573908697a..87b6b55c654 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd @@ -2,7 +2,7 @@ cimport cython from libc.stdint cimport uint64_t from sage.ext.memory_allocator cimport MemoryAllocator from sage.structure.sage_object cimport SageObject -from .face_iterator cimport FaceIterator +from .face_iterator cimport FaceIterator, CombinatorialFace from .list_of_faces cimport ListOfFaces from .list_of_all_faces cimport ListOfAllFaces @@ -14,28 +14,35 @@ cdef class CombinatorialPolyhedron(SageObject): cdef tuple _equalities # stores equalities, given on input (might belong to Hrep) cdef int _dimension # stores dimension, -2 on init cdef unsigned int _length_Hrep # Hrep might include equalities - cdef unsigned int _length_Vrep # Vrep might include rays/lines - cdef size_t _nr_facets # length Hrep without equalities + cdef unsigned int _length_Vrepr # Vrep might include rays/lines + cdef size_t _n_facets # length Hrep without equalities cdef bint _unbounded # ``True`` iff Polyhedron is unbounded - cdef int _nr_lines # number of affinely independent lines in the Polyhedron + cdef int _n_lines # number of affinely independent lines in the Polyhedron cdef ListOfFaces bitrep_facets # facets in bit representation - cdef ListOfFaces bitrep_vertices # vertices in bit representation + cdef ListOfFaces bitrep_Vrepr # vertices in bit representation cdef tuple _f_vector # Edges, ridges and incidences are stored in a pointer of pointers. - # This number determines how many edges are stored in ``edges[0]``, - # how many ridges are stored in ``ridges[0]`` etc. + # The first edge has vertices ``edges[0][0]`` and ``edges[0][1]``, + # the second edge has vertices ``edges[0][2]`` and ``edges[0][3]``, etc. + # There are ``_length_edges_list`` edges in ``edges[i]``, so the edge + # ``_length_edges_list + 1`` has vertices ``edges[1][0]`` and ``edges[1][1]``. + # Likewise for ridges and incidences. cdef size_t _length_edges_list - cdef size_t **_edges # stores edges - cdef size_t _nr_edges - cdef size_t **_ridges # stores ridges - cdef size_t _nr_ridges - cdef size_t **_face_lattice_incidences # stores incidences in Hasse diagram - cdef size_t _nr_face_lattice_incidences + cdef size_t **_edges # stores edges labeled by vertex indices + cdef size_t _n_edges + cdef size_t **_ridges # stores ridges labeld by facet indices + cdef size_t _n_ridges + cdef size_t **_face_lattice_incidences # stores incidences in Hasse diagram labeled indices of the faces + cdef size_t _n_face_lattice_incidences cdef ListOfAllFaces _all_faces # class to generate Hasse diagram incidences - cdef tuple _mem_tuple # stores MemoryAllocators for edges, ridges etc. + + # Space for edges, ridges, etc. is allocated with ``MemoryAllocators``. + # Upon sucess they are copied to ``_mem_tuple``. + # Thus deallocation (at the correct time) is taken care of. + cdef tuple _mem_tuple cdef FaceIterator _face_iter(self, bint dual, int dimension) cdef int _compute_f_vector(self) except -1 diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index a0eb740af4c..9d27fc2bdf8 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -11,17 +11,18 @@ the ridges and the face lattice. Terminology used in this module: -- Vertices -- ``[vertices, rays, lines]`` of the polyhedron. +- Vrepr -- ``[vertices, rays, lines]`` of the polyhedron. +- Hrepr -- inequalities and equalities of the polyhedron. - Facets -- facets of the polyhedron. -- vertex representation -- represents a face by the list of vertices it contains. -- facet representation -- represents a face by the list of facets it is contained in. +- Vrepresentation -- represents a face by the list of Vrepr it contains. +- Hrepresentation -- represents a face by a list of Hrepr it is contained in. - bit representation -- represents incidences as ``uint64_t``-array, where each bit represents one incidence. There might be trailing zeros, to fit alignment requirements. In most instances, faces are represented by the bit representation, where each bit corresponds to - a vertex or facet. Thus a bit representation can either be - a vertex or facet representation depending on context. + a Vrepr or facet. Thus a bit representation can either be + a Vrepr or facet representation depending on context. EXAMPLES: @@ -59,7 +60,7 @@ Face lattice:: sage: C.face_lattice() Finite lattice containing 82 elements -:class:`~sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator`:: +Face iterator:: sage: C.face_iter() Iterator over the proper faces of a polyhedron of dimension 4 @@ -83,19 +84,20 @@ AUTHOR: #***************************************************************************** from __future__ import absolute_import, division, print_function +import numbers from sage.rings.integer import Integer from sage.graphs.graph import Graph from sage.graphs.digraph import DiGraph from sage.combinat.posets.lattices import FiniteLatticePoset -from sage.geometry.polyhedron.base import is_Polyhedron -from sage.geometry.lattice_polytope import is_LatticePolytope -from sage.structure.element import is_Matrix +from sage.geometry.polyhedron.base import Polyhedron_base +from sage.geometry.lattice_polytope import LatticePolytopeClass +from sage.structure.element import Matrix from sage.misc.misc import is_iterator from .conversions \ import incidence_matrix_to_bit_repr_of_facets, \ - incidence_matrix_to_bit_repr_of_vertices, \ + incidence_matrix_to_bit_repr_of_Vrepr, \ facets_tuple_to_bit_repr_of_facets, \ - facets_tuple_to_bit_repr_of_vertices + facets_tuple_to_bit_repr_of_Vrepr from sage.rings.integer cimport smallInteger from cysignals.signals cimport sig_check, sig_block, sig_unblock @@ -114,26 +116,26 @@ cdef class CombinatorialPolyhedron(SageObject): * or a :class:`~sage.geometry.lattice_polytope.LatticePolytopeClass` * or an ``incidence_matrix`` as in :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.incidence_matrix` - In this case you should also specify the ``vertices``, ``facets`` - and ``nr_lines`` arguments. - * or a triple ``[list, tuple, iterator]`` of facets, each facet given as + In this case you should also specify the ``Vrepr`` and ``facets`` arguments + If the polyhedron is unbounded, then ``n_lines`` as well + * or list of facets, each facet given as a list of ``[vertices, rays, lines]`` if the polyhedron is unbounded, - then rays and lines are required if the polyehdron contains no lines, - the rays can be thought of as the vertices of the facets deleted from a - bounded polyhedron see + then rays and lines and the extra argument ``nr_lines`` are required + if the polyehdron contains no lines, the rays can be thought of + as the vertices of the facets deleted from a bounded polyhedron see :class:`~sage.geometry.polyhedron.parent.Polyhedron_base` on how to use rays and lines. * or an integer, representing the dimension of a polyhedron equal to its affine hull - - ``vertices`` -- (optional) when ``data`` is an incidence matrix, it should + - ``Vrepr`` -- (optional) when ``data`` is an incidence matrix, it should be the list of ``[vertices, rays, lines]``, if the rows in the incidence_matrix should correspond to names - - ``facets`` -- (optional) when ``data`` is an incidence matrix or a triple, it - should be a list of facets that would be used instead of indices (of the columns + - ``facets`` -- (optional) when ``data`` is an incidence matrix or a list of facets, + it should be a list of facets that would be used instead of indices (of the columns of the incidence matrix). - - ``nr_lines`` -- (optional) when ``data` is an incidence matrix or a triple and - the polyhedra is unbounded this needs to be set to the dimension of the maximal - linear subspace contained in the polyhedron + - ``n_lines`` -- (semi-optional) when ``data` is an incidence matrix or a + list of facets and the polyhedron is unbounded this needs to be set to + the dimension of the maximal linear subspace contained in the polyhedron EXAMPLES: @@ -154,10 +156,10 @@ cdef class CombinatorialPolyhedron(SageObject): an incidence matrix:: sage: data = Polyhedron(rays=[[0,1]]).incidence_matrix() - sage: CombinatorialPolyhedron(data, nr_lines=0) + sage: CombinatorialPolyhedron(data, n_lines=0) Combinatorial type of a polyhedron of dimension 1 with 1 vertices - sage: C = CombinatorialPolyhedron(data, vertices=['myvertex'], - ....: facets=['myfacet'], nr_lines=0) + sage: C = CombinatorialPolyhedron(data, Vrepr=['myvertex'], + ....: facets=['myfacet'], n_lines=0) sage: C.Vrepresentation() ('myvertex',) sage: C.Hrepresentation() @@ -196,7 +198,7 @@ cdef class CombinatorialPolyhedron(SageObject): sage: data = P.incidence_matrix() sage: vert = P.Vrepresentation() - sage: C = CombinatorialPolyhedron(data, vertices=vert) + sage: C = CombinatorialPolyhedron(data, Vrepr=vert) sage: C Combinatorial type of a polyhedron of dimension 2 with 3 vertices sage: C.f_vector() @@ -208,7 +210,7 @@ cdef class CombinatorialPolyhedron(SageObject): The correct usage is:: - sage: C = CombinatorialPolyhedron(data, vertices=vert, nr_lines=1) + sage: C = CombinatorialPolyhedron(data, Vrepr=vert, n_lines=1) sage: C Combinatorial type of a polyhedron of dimension 2 with 0 vertices sage: C.f_vector() @@ -228,22 +230,24 @@ cdef class CombinatorialPolyhedron(SageObject): (A vertex at (0, 0),) sage: data = P.incidence_matrix() sage: vert = P.Vrepresentation() - sage: C = CombinatorialPolyhedron(data, vertices=vert) + sage: C = CombinatorialPolyhedron(data, Vrepr=vert) sage: C Combinatorial type of a polyhedron of dimension 2 with 3 vertices sage: C.f_vector() (1, 1, 2, 1) sage: C.vertices() (A vertex at (0, 0), A vertex at (0, 0), A vertex at (0, 0)) - sage: C = CombinatorialPolyhedron(data, vertices=vert, nr_lines=0) + sage: C = CombinatorialPolyhedron(data, Vrepr=vert, n_lines=0) sage: C Combinatorial type of a polyhedron of dimension 2 with 1 vertices sage: C.f_vector() (1, 1, 2, 1) sage: C.vertices() (A vertex at (0, 0),) + sage: CombinatorialPolyhedron(3r) + Combinatorial type of a polyhedron of dimension 3 with 0 vertices """ - def __init__(self, data, vertices=None, facets=None, nr_lines=None): + def __init__(self, data, Vrepr=None, facets=None, n_lines=None): r""" Initialize :class:`CombinatorialPolyhedron`. @@ -252,7 +256,7 @@ cdef class CombinatorialPolyhedron(SageObject): TESTS:: sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3], - ....: [0,2,3],[1,2,3]]) # indirect doctests + ....: [0,2,3],[1,2,3]]) # indirect doctest sage: TestSuite(sage.geometry.polyhedron.combinatorial_polyhedron.base.CombinatorialPolyhedron).run() """ @@ -273,43 +277,47 @@ cdef class CombinatorialPolyhedron(SageObject): # ``self._length_edges_list*2*sizeof(size_t *)``. self._length_edges_list = 16348 - if is_Polyhedron(data): + if isinstance(data, Polyhedron_base): # input is ``Polyhedron`` - vertices = data.Vrepresentation() + Vrepr = data.Vrepresentation() facets = tuple(inequality for inequality in data.Hrepresentation()) if not data.is_compact(): self._unbounded = True - self._nr_lines = int(data.n_lines()) + self._n_lines = int(data.n_lines()) else: self._unbounded = False - self._nr_lines = 0 + self._n_lines = 0 data = data.incidence_matrix() - elif is_LatticePolytope(data): + elif isinstance(data, LatticePolytopeClass): # input is ``LatticePolytope`` self._unbounded = False - self._nr_lines = 0 - vertices = data.vertices() - self._length_Vrep = len(vertices) + self._n_lines = 0 + Vrepr = data.vertices() + self._length_Vrepr = len(Vrepr) facets = data.facets() self._length_Hrep = len(facets) data = tuple(tuple(vert for vert in facet.vertices()) for facet in facets) else: # Input is different from ``Polyhedron`` and ``LatticePolytope``. - if nr_lines is None: + if n_lines is None: # bounded polyhedron self._unbounded = False - self._nr_lines = 0 - else: + self._n_lines = 0 + elif n_lines >= 0: # unbounded polyhedron + # will be slower but not incorrect if ``n_lines == 0`` + assert isinstance(n_lines, numbers.Integral), "n_lines need to be an integer" self._unbounded = True - self._nr_lines = int(nr_lines) + self._n_lines = int(n_lines) + else: + raise ValueError("n_lines must be a non-negative integer") - if vertices: + if Vrepr: # store vertices names - self._V = tuple(vertices) + self._V = tuple(Vrepr) self._Vinv = {v: i for i,v in enumerate(self._V)} else: self._V = None @@ -322,7 +330,9 @@ cdef class CombinatorialPolyhedron(SageObject): test = [1] * len(facets) # 0 if that facet is an equality for i in range(len(facets)): if hasattr(facets[i], "is_inequality"): - # At the moment this test only works for input being + # We remove equalites. + # At the moment only equalities with this attribute ``True`` + # will be detected. if not facets[i].is_inequality(): test[i] = 0 self._H = tuple(facets[i] for i in range(len(facets)) if test[i]) @@ -331,32 +341,32 @@ cdef class CombinatorialPolyhedron(SageObject): else: self._H = None - if is_Matrix(data): + if isinstance(data, Matrix): # Input is incidence-matrix or was converted to it. self._length_Hrep = data.ncols() - self._length_Vrep = data.nrows() + self._length_Vrepr = data.nrows() # Initializing the facets in their Bit-representation. self.bitrep_facets = incidence_matrix_to_bit_repr_of_facets(data) - # Initializing the vertices as their Bit-representation. - self.bitrep_vertices = incidence_matrix_to_bit_repr_of_vertices(data) + # Initializing the Vrepr as their Bit-representation. + self.bitrep_Vrepr = incidence_matrix_to_bit_repr_of_Vrepr(data) - self._nr_facets = self.bitrep_facets.nr_faces + self._n_facets = self.bitrep_facets.n_faces - elif isinstance(data, Integer): + elif isinstance(data, numbers.Integral): # To construct a trivial polyhedron, equal to its affine hull, # one can give an Integer as Input. if data < -1: ValueError("any polyhedron must have dimension at least -1") - self._nr_facets = 0 + self._n_facets = 0 self._dimension = data # Initializing the facets in their Bit-representation. self.bitrep_facets = facets_tuple_to_bit_repr_of_facets((), 0) - # Initializing the vertices as their Bit-representation. - self.bitrep_vertices = facets_tuple_to_bit_repr_of_vertices((), 0) + # Initializing the Vrepr as their Bit-representation. + self.bitrep_Vrepr = facets_tuple_to_bit_repr_of_Vrepr((), 0) else: # Input is a "list" of facets. @@ -366,34 +376,34 @@ cdef class CombinatorialPolyhedron(SageObject): data = tuple(data) if self._V is None: - # Get the names of the vertices. - vertices = sorted(set.union(*map(set, data))) - nr_vertices = len(vertices) - if vertices != range(len(vertices)): - self._V = tuple(vertices) + # Get the names of the Vrepr. + Vrepr = sorted(set.union(*map(set, data))) + length_Vrepr = len(Vrepr) + if Vrepr != range(len(Vrepr)): + self._V = tuple(Vrepr) self._Vinv = {v: i for i,v in enumerate(self._V)} else: # Assuming the user gave as correct names for the vertices # and labeled them instead by `0,...,n`. - nr_vertices = len(self._V) + length_Vrepr = len(self._V) - self._length_Vrep = nr_vertices + self._length_Vrepr = length_Vrepr - # Relabel the vertices to be `0,...,n`. + # Relabel the Vrepr to be `0,...,n`. if self._V is not None: def f(v): return self._Vinv[v] else: def f(v): return int(v) facets = tuple(tuple(f(i) for i in j) for j in data) - self._nr_facets = len(facets) + self._n_facets = len(facets) self._length_Hrep = len(facets) # Initializing the facets in their Bit-representation. - self.bitrep_facets = facets_tuple_to_bit_repr_of_facets(facets, nr_vertices) + self.bitrep_facets = facets_tuple_to_bit_repr_of_facets(facets, length_Vrepr) - # Initializing the vertices as their Bit-representation. - self.bitrep_vertices = facets_tuple_to_bit_repr_of_vertices(facets, nr_vertices) + # Initializing the Vrepr as their Bit-representation. + self.bitrep_Vrepr = facets_tuple_to_bit_repr_of_Vrepr(facets, length_Vrepr) def _repr_(self): r""" @@ -428,7 +438,7 @@ cdef class CombinatorialPolyhedron(SageObject): """ return "Combinatorial type of a polyhedron of "\ "dimension %s with %s vertices" \ - % (self.dimension(), self.nr_vertices()) + % (self.dimension(), self.n_vertices()) def __reduce__(self): r""" @@ -441,8 +451,8 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C1 = loads(C.dumps()) sage: it = C.face_iter() sage: it1 = C1.face_iter() - sage: tup = tuple((it.vertex_repr(), it.facet_repr()) for _ in it) - sage: tup1 = tuple((it1.vertex_repr(), it1.facet_repr()) for _ in it1) + sage: tup = tuple((face.Vrepr(), face.Hrepr()) for face in it) + sage: tup1 = tuple((face.Vrepr(), face.Hrepr()) for face in it1) sage: tup == tup1 True @@ -451,8 +461,8 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C1 = loads(C.dumps()) sage: it = C.face_iter() sage: it1 = C1.face_iter() - sage: tup = tuple((it.vertex_repr(), it.facet_repr()) for _ in it) - sage: tup1 = tuple((it1.vertex_repr(), it1.facet_repr()) for _ in it1) + sage: tup = tuple((face.Vrepr(), face.Hrepr()) for face in it) + sage: tup1 = tuple((face.Vrepr(), face.Hrepr()) for face in it1) sage: tup == tup1 True @@ -461,8 +471,8 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C1 = loads(C.dumps()) sage: it = C.face_iter() sage: it1 = C1.face_iter() - sage: tup = tuple((it.vertex_repr(), it.facet_repr()) for _ in it) - sage: tup1 = tuple((it1.vertex_repr(), it1.facet_repr()) for _ in it1) + sage: tup = tuple((face.Vrepr(), face.Hrepr()) for face in it) + sage: tup1 = tuple((face.Vrepr(), face.Hrepr()) for face in it1) sage: tup == tup1 True @@ -472,17 +482,17 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C1 = loads(C.dumps()) sage: it = C.face_iter() sage: it1 = C1.face_iter() - sage: tup = tuple((it.vertex_repr(), it.facet_repr()) for _ in it) - sage: tup1 = tuple((it1.vertex_repr(), it1.facet_repr()) for _ in it1) + sage: tup = tuple((face.Vrepr(), face.Hrepr()) for face in it) + sage: tup1 = tuple((face.Vrepr(), face.Hrepr()) for face in it1) sage: tup == tup1 True """ - nr_lines = None + n_lines = None if self._unbounded: - nr_lines = smallInteger(self._nr_lines) + n_lines = smallInteger(self._n_lines) # Give a constructor by list of facets. return (CombinatorialPolyhedron, (self.facets(), - self.Vrepresentation(), self.Hrepresentation(), nr_lines)) + self.Vrepresentation(), self.Hrepresentation(), n_lines)) def Vrepresentation(self): r""" @@ -502,7 +512,7 @@ cdef class CombinatorialPolyhedron(SageObject): if self._V is not None: return self._V else: - return tuple(smallInteger(i) for i in range(self._length_Vrep)) + return tuple(smallInteger(i) for i in range(self._length_Vrepr)) def Hrepresentation(self): r""" @@ -563,12 +573,12 @@ cdef class CombinatorialPolyhedron(SageObject): """ if self._dimension == -2: # Dimension not computed yet. - if self._nr_facets == 0: + if self._n_facets == 0: # The dimension of a trivial polyhedron is assumed to contain # exactly one "vertex" and for each dimension one "line" as in # :class:`~sage.geometry.polyhedron.parent.Polyhedron_base` - self._dimension = self._length_Vrep - 1 - elif self._unbounded or self._nr_facets <= self._length_Vrep: + self._dimension = self._length_Vrepr - 1 + elif self._unbounded or self._n_facets <= self._length_Vrepr: self._dimension = self.bitrep_facets.compute_dimension() else: # If the polyhedron has many facets, @@ -577,7 +587,7 @@ cdef class CombinatorialPolyhedron(SageObject): self._dimension = self.bitrep_facets.compute_dimension() return smallInteger(self._dimension) - def nr_vertices(self): + def n_vertices(self): r""" Return the number of vertices. @@ -587,49 +597,49 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.cube() sage: C = CombinatorialPolyhedron(P) - sage: C.nr_vertices() + sage: C.n_vertices() 8 sage: P = polytopes.cyclic_polytope(4,20) sage: C = CombinatorialPolyhedron(P) - sage: C.nr_vertices() + sage: C.n_vertices() 20 sage: P = Polyhedron(lines=[[0,1]], vertices=[[1,0], [-1,0]]) sage: C = CombinatorialPolyhedron(P) - sage: C.nr_vertices() + sage: C.n_vertices() 0 sage: P = Polyhedron(rays=[[1,0,0], [0,1,0]], lines=[[0,0,1]]) sage: C = CombinatorialPolyhedron(P) - sage: C.nr_vertices() + sage: C.n_vertices() 0 sage: C = CombinatorialPolyhedron(4) sage: C.f_vector() (1, 0, 0, 0, 0, 1) - sage: C.nr_vertices() + sage: C.n_vertices() 0 sage: C = CombinatorialPolyhedron(0) sage: C.f_vector() (1, 1) - sage: C.nr_vertices() + sage: C.n_vertices() 1 """ if self.dimension() == 0: # This specific trivial polyhedron needs special attention. - return Integer(1) + return smallInteger(1) elif not self._unbounded: # In the unbounded case, we need to actually computed the vertices, - # the the V-representation contains also ``lines`` and ``rays``. - return Integer(self._length_Vrep) + # the the Vrepr contains also ``lines`` and ``rays``. + return Integer(self._length_Vrepr) else: return Integer(len(self.vertices())) def vertices(self, names=True): r""" - Return the elements in the ``Vrepresentation`` that are vertices. + Return the elements in the Vrepresentation that are vertices. In case of an unbounded polyhedron, there might be lines and rays in the Vrepresentation. @@ -680,19 +690,19 @@ cdef class CombinatorialPolyhedron(SageObject): if names and self._V: return (self._V[0],) else: - return (Integer(0),) + return (smallInteger(0),) dual = False if not self._unbounded: # In the bounded case, we already know all the vertices. - # Whereas, in the unbounded case, some of those "vertices" might + # Whereas, in the unbounded case, some elements in Vrepr might # be ``rays`` or ``lines``. dual = True # Get all `0`-dimensional faces from :meth:`face_iter`. face_iter = self.face_iter(0, dual=dual) - return tuple(face_iter.vertex_repr(names=names)[0] for _ in face_iter) + return tuple(face.Vrepr(names=names)[0] for face in face_iter) - def nr_facets(self): + def n_facets(self): r""" Return the number of facets. @@ -702,46 +712,46 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.cube() sage: C = CombinatorialPolyhedron(P) - sage: C.nr_facets() + sage: C.n_facets() 6 sage: P = polytopes.cyclic_polytope(4,20) sage: C = CombinatorialPolyhedron(P) - sage: C.nr_facets() + sage: C.n_facets() 170 sage: P = Polyhedron(lines=[[0,1]], vertices=[[1,0], [-1,0]]) sage: C = CombinatorialPolyhedron(P) - sage: C.nr_facets() + sage: C.n_facets() 2 sage: P = Polyhedron(rays=[[1,0], [-1,0], [0,1]]) sage: C = CombinatorialPolyhedron(P) - sage: C.nr_facets() + sage: C.n_facets() 1 sage: C = CombinatorialPolyhedron(-1) sage: C.f_vector() (1,) - sage: C.nr_facets() + sage: C.n_facets() 0 sage: C = CombinatorialPolyhedron(0) sage: C.f_vector() (1, 1) - sage: C.nr_facets() + sage: C.n_facets() 1 """ if unlikely(self.dimension() == 0): # This trivial polyhedron needs special attention. - return Integer(1) - return Integer(self._nr_facets) + return smallInteger(1) + return smallInteger(self._n_facets) def facets(self, names=True): r""" Return the facets as lists of ``[vertices, rays, lines]``. - If ``names`` is ``False``, then the vertices in the facets + If ``names`` is ``False``, then the Vrepresentatives in the facets are given by their indices in the Vrepresentation. EXAMPLES:: @@ -790,10 +800,10 @@ cdef class CombinatorialPolyhedron(SageObject): # on input, so that pickle/unpickle by :meth:`reduce` works. # Every facet knows its index by the facet representation. face_iter = self.face_iter(self.dimension() - 1, dual=False) - facets = [None] * self._nr_facets - for _ in face_iter: - index = face_iter.facet_repr(names=False)[0] - verts = face_iter.vertex_repr(names=names) + facets = [None] * self._n_facets + for face in face_iter: + index = face.Hrepr(names=False)[0] + verts = face.Vrepr(names=names) facets[index] = verts return tuple(facets) @@ -802,7 +812,7 @@ cdef class CombinatorialPolyhedron(SageObject): r""" Return the edges of the polyhedron, i.e. the rank 1 faces. - If ``names`` is set to ``False``, then the vertices in the edges + If ``names`` is set to ``False``, then the Vrepresentatives in the edges are given by their indices in the Vrepresentation. .. NOTE:: @@ -873,7 +883,7 @@ cdef class CombinatorialPolyhedron(SageObject): # compute the edges. if self._unbounded: self._compute_edges(dual=False) - elif self._length_Vrep > self._nr_facets*self._nr_facets: + elif self._length_Vrepr > self._n_facets*self._n_facets: # This is a wild estimate # that in this case it is better not to use the dual. self._compute_edges(dual=False) @@ -892,7 +902,7 @@ cdef class CombinatorialPolyhedron(SageObject): # Hence, edges are stored in an array of arrays, # with each array containing ``len_edge_list`` of edges. - # Mapping the indices of the vertices to the names, if requested. + # Mapping the indices of the Vrepr to the names, if requested. if self._V is not None and names is True: def f(size_t i): return self._V[i] else: @@ -905,13 +915,13 @@ cdef class CombinatorialPolyhedron(SageObject): return f(self._edges[i // len_edge_list][2*(i % len_edge_list)+1]) cdef size_t j - return tuple((vertex_one(j), vertex_two(j)) for j in range(self._nr_edges)) + return tuple((vertex_one(j), vertex_two(j)) for j in range(self._n_edges)) def edge_graph(self, names=True): r""" Return the edge graph. - If ``names`` is set to ``False``, the vertices will carry names + If ``names`` is set to ``False``, the Vrepresenatives will carry names according to the indexing of the Vrepresentation. EXAMPLES:: @@ -1002,7 +1012,7 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C.ridges() () sage: it = C.face_iter(0) - sage: for d in it: it.facet_repr() + sage: for face in it: face.Hrepr() (An inequality (1, 0) x + 0 >= 0, An equation (0, 1) x + 0 == 0) TESTS:: @@ -1025,7 +1035,7 @@ cdef class CombinatorialPolyhedron(SageObject): # compute the ridges. if self._unbounded: self._compute_ridges(dual=False) - elif self._length_Vrep*self._length_Vrep < self._nr_facets: + elif self._length_Vrepr*self._length_Vrepr < self._n_facets: # This is a wild estimate # that in this case it is better to use the dual. self._compute_edges(dual=True) @@ -1034,7 +1044,7 @@ cdef class CombinatorialPolyhedron(SageObject): self._compute_ridges(dual=False) if self._ridges is NULL: raise ValueError('could not determine ridges') - nr_ridges = self._nr_ridges + n_ridges = self._n_ridges # The ridges are being saved in a list basically. # The first entry represents the first facet of the first ridge. @@ -1045,7 +1055,7 @@ cdef class CombinatorialPolyhedron(SageObject): # Hence, ridges are stored in an array of arrays, # with each array containing ``len_ridge_list`` of ridges. - # Mapping the indices of the vertices to the names, if requested. + # Mapping the indices of the Vepr to the names, if requested. if self._H is not None and names is True: def f(size_t i): return self._H[i] else: @@ -1063,10 +1073,10 @@ cdef class CombinatorialPolyhedron(SageObject): return tuple( ((self._equalities + (facet_one(i),)), (self._equalities + (facet_two(i),))) - for i in range(nr_ridges)) + for i in range(n_ridges)) else: return tuple((facet_one(i), facet_two(i)) - for i in range(nr_ridges)) + for i in range(n_ridges)) def ridge_graph(self, names=True): r""" @@ -1175,45 +1185,43 @@ cdef class CombinatorialPolyhedron(SageObject): .. NOTE:: :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator` - is more than just a plain iterator. - By default it will iterate over the dimensions of the faces, but - more information can be received. + can ignore subfaces or supfaces of the current face. EXAMPLES:: sage: P = polytopes.permutahedron(5) sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter(dimension=2) - sage: next(it) - 2 - sage: it.vertex_repr() + sage: face = next(it); face + Combinatorial type of a 2-dimensional face of a 4-dimensional polyhedron + sage: face.Vrepr() (A vertex at (4, 1, 5, 2, 3), A vertex at (4, 2, 5, 1, 3), A vertex at (5, 1, 4, 2, 3), A vertex at (5, 2, 4, 1, 3)) - sage: next(it) - 2 - sage: it.vertex_repr() + sage: face = next(it); face + Combinatorial type of a 2-dimensional face of a 4-dimensional polyhedron + sage: face.Vrepr() (A vertex at (4, 1, 5, 2, 3), A vertex at (4, 1, 5, 3, 2), A vertex at (5, 1, 4, 2, 3), A vertex at (5, 1, 4, 3, 2)) - sage: it.facet_repr() + sage: face.Hrepr() (An inequality (0, 1, 0, 0, 0) x - 1 >= 0, An inequality (0, 1, 0, 1, 1) x - 6 >= 0, An equation (1, 1, 1, 1, 1) x - 15 == 0) - sage: it.facet_repr(names=False) + sage: face.Hrepr(names=False) (25, 29) - sage: next(it) - 2 - sage: it.facet_repr(names=False) + sage: face = next(it); face + Combinatorial type of a 2-dimensional face of a 4-dimensional polyhedron + sage: face.Hrepr(names=False) (12, 29) - sage: it.vertex_repr(names=False) + sage: face.Vrepr(names=False) (76, 77, 82, 83, 88, 89) sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3],[0,2,3],[1,2,3]]) sage: it = C.face_iter() - sage: for _ in it: it.vertex_repr() + sage: for face in it: face.Vrepr() (1, 2, 3) (0, 2, 3) (0, 1, 3) @@ -1232,19 +1240,20 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = Polyhedron(rays=[[1,0],[0,1]], vertices=[[1,0],[0,1]]) sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter(1) - sage: for _ in it: it.vertex_repr() + sage: for face in it: face.Vrepr() (A vertex at (0, 1), A vertex at (1, 0)) (A ray in the direction (1, 0), A vertex at (1, 0)) (A ray in the direction (0, 1), A vertex at (0, 1)) .. SEEALSO:: - :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator`. + :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator`, + :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face.CombinatorialFace`. """ cdef FaceIterator face_iter if dual is None: # Determine the faster way, to iterate through all faces. - if self._unbounded or self._nr_facets <= self._length_Vrep: + if self._unbounded or self._n_facets <= self._length_Vrepr: dual = False else: dual = True @@ -1278,21 +1287,16 @@ cdef class CombinatorialPolyhedron(SageObject): .. NOTE:: - Use :meth:`CombinatorialPolyhedron.face_lattice_dimension` to get - the dimension for each element in the Face Lattice. - Use :meth:`CombinatorialPolyhedron.face_lattice_vertex_repr` to get - the vertex representation for each element in the Face Lattice. - Use :meth:`CombinatorialPolyhedron.face_lattice_facet_repr` to get - the facet_repr for each element in the Face Lattice. + Use :meth:`CombinatorialPolyhedron.face_by_face_lattice_index` to get + the face for each index. .. WARNING:: The labeling of the face lattice might depend on archicture and implementation. Relabeling the face lattice with - :meth:`CombinatorialPolyhedron.face_lattice_vertex_repr` and/or - :meth:`CombinatorialPolyhedron.face_lattice_facet_repr` will be - platform independent. + :meth:`CombinatorialPolyhedron.face_by_face_lattice_index` or + the properties obtained from this face will be platform independent EXAMPLES:: @@ -1332,7 +1336,7 @@ cdef class CombinatorialPolyhedron(SageObject): raise TypeError("could not determine face lattice") cdef size_t **incidences = self._face_lattice_incidences - cdef size_t nr_incidences = self._nr_face_lattice_incidences + cdef size_t n_incidences = self._n_face_lattice_incidences cdef size_t len_incidence_list = self._length_edges_list # The incidences are being saved in a list basically. @@ -1346,20 +1350,20 @@ cdef class CombinatorialPolyhedron(SageObject): # Getting the indices of the `i`-th incidence. def face_one(size_t i): - return Integer(incidences[i // len_incidence_list][2*(i % len_incidence_list)]) + return smallInteger(incidences[i // len_incidence_list][2*(i % len_incidence_list)]) def face_two(size_t i): - return Integer(incidences[i // len_incidence_list][2*(i % len_incidence_list)+1]) + return smallInteger(incidences[i // len_incidence_list][2*(i % len_incidence_list)+1]) # Edges of the face-lattice/Hasse diagram. cdef size_t j edges = tuple((face_one(j), face_two(j)) - for j in range(nr_incidences)) + for j in range(n_incidences)) V = tuple(range(sum(self._f_vector))) D = DiGraph([V, edges], format='vertices_and_edges') return FiniteLatticePoset(D) - def face_lattice_dimension(self, index): + def _face_lattice_dimension(self, index): r""" Return for each element in :meth:`CombinatorialPolyhedron.face_lattice` its dimension. @@ -1370,7 +1374,7 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C = CombinatorialPolyhedron(P) sage: F = C.face_lattice() sage: def f(i): - ....: return (i, C.face_lattice_dimension(i)) + ....: return (i, C._face_lattice_dimension(i)) ....: sage: G = F.relabel(f) sage: set(G._elements) @@ -1413,15 +1417,12 @@ cdef class CombinatorialPolyhedron(SageObject): # ``k = sum(f_vector[:d])``. return max(d for d in range(dim+2) if sum(f_vector[:d]) <= index) - 1 - def face_lattice_vertex_repr(self, index, names=True): + def face_by_face_lattice_index(self, index): r""" - Return for each element in :meth:`CombinatorialPolyhedron.face_lattice` - its vertex-representation as in - :meth:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_all_faces.ListOfAllFaces.vertex_repr` - or :meth:`~sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator.vertex_repr`. + Return the element of :meth:`CombinatorialPolyhedron.face_lattice` with corresponding index. - If ``names`` is set to ``True``, then names of the - ``[vertices, rays, lines]`` are used. + The element will be returned as + :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face.CombinatorialFace`. EXAMPLES:: @@ -1430,182 +1431,59 @@ cdef class CombinatorialPolyhedron(SageObject): sage: F = C.face_lattice() sage: F Finite lattice containing 28 elements - sage: G = F.relabel(C.face_lattice_vertex_repr) + sage: G = F.relabel(C.face_by_face_lattice_index) sage: G._elements - ((), - (A vertex at (-1, -1, -1),), - (A vertex at (-1, -1, 1),), - (A vertex at (-1, -1, -1), A vertex at (-1, -1, 1)), - (A vertex at (-1, 1, -1),), - (A vertex at (-1, -1, -1), A vertex at (-1, 1, -1)), - (A vertex at (-1, 1, 1),), - (A vertex at (-1, -1, 1), A vertex at (-1, 1, 1)), - (A vertex at (-1, 1, -1), A vertex at (-1, 1, 1)), - (A vertex at (-1, -1, -1), - A vertex at (-1, -1, 1), - A vertex at (-1, 1, -1), - A vertex at (-1, 1, 1)), - (A vertex at (1, -1, -1),), - (A vertex at (-1, -1, -1), A vertex at (1, -1, -1)), - (A vertex at (1, -1, 1),), - (A vertex at (-1, -1, 1), A vertex at (1, -1, 1)), - (A vertex at (1, -1, -1), A vertex at (1, -1, 1)), - (A vertex at (-1, -1, -1), - A vertex at (-1, -1, 1), - A vertex at (1, -1, -1), - A vertex at (1, -1, 1)), - (A vertex at (1, 1, -1),), - (A vertex at (-1, 1, -1), A vertex at (1, 1, -1)), - (A vertex at (1, -1, -1), A vertex at (1, 1, -1)), - (A vertex at (-1, -1, -1), - A vertex at (-1, 1, -1), - A vertex at (1, -1, -1), - A vertex at (1, 1, -1)), - (A vertex at (1, 1, 1),), - (A vertex at (-1, 1, 1), A vertex at (1, 1, 1)), - (A vertex at (1, -1, 1), A vertex at (1, 1, 1)), - (A vertex at (-1, -1, 1), - A vertex at (-1, 1, 1), - A vertex at (1, -1, 1), - A vertex at (1, 1, 1)), - (A vertex at (1, 1, -1), A vertex at (1, 1, 1)), - (A vertex at (-1, 1, -1), - A vertex at (-1, 1, 1), - A vertex at (1, 1, -1), - A vertex at (1, 1, 1)), - (A vertex at (1, -1, -1), - A vertex at (1, -1, 1), - A vertex at (1, 1, -1), - A vertex at (1, 1, 1)), - (A vertex at (-1, -1, -1), - A vertex at (-1, -1, 1), - A vertex at (-1, 1, -1), - A vertex at (-1, 1, 1), - A vertex at (1, -1, -1), - A vertex at (1, -1, 1), - A vertex at (1, 1, -1), - A vertex at (1, 1, 1))) + (Combinatorial type of a -1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 3-dimensional face of a 3-dimensional polyhedron) sage: P = Polyhedron(rays=[[0,1], [1,0]]) sage: C = CombinatorialPolyhedron(P) sage: F = C.face_lattice() - sage: G = F.relabel(C.face_lattice_vertex_repr) - sage: G._elements - ((), - (A vertex at (0, 0),), - (A vertex at (0, 0), A ray in the direction (0, 1)), - (A vertex at (0, 0), A ray in the direction (1, 0)), - (A vertex at (0, 0), - A ray in the direction (0, 1), - A ray in the direction (1, 0))) - - sage: def f(i): return C.face_lattice_vertex_repr(i, False) - sage: G = F.relabel(f) + sage: G = F.relabel(C.face_by_face_lattice_index) sage: G._elements - ((), (0,), (0, 1), (0, 2), (0, 1, 2)) - """ - self._record_all_faces() # Initalize ``_all_faces``, if not done yet. - dim = self.face_lattice_dimension(index) # Determine dimension to that index. - newindex = index - sum(self._f_vector[:dim + 1]) # Index in that level-set. + (Combinatorial type of a -1-dimensional face of a 2-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 2-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 2-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 2-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 2-dimensional polyhedron) - # Let ``_all_faces`` determine vertex-representation. - return self._all_faces.vertex_repr(dim, newindex, names=names) - - def face_lattice_facet_repr(self, index, names=True): - r""" - Return for each element in :meth:`CombinatorialPolyhedron.face_lattice` - its facet-representation as in - :meth:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_all_faces.ListOfAllFaces.facet_repr` - or :meth:`~sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator.facet_repr`. - - If ``names`` is set to ``True``, then names of the - ``facets`` are used. - - EXAMPLES:: - - sage: P = polytopes.cube() - sage: C = CombinatorialPolyhedron(P) - sage: F = C.face_lattice() - sage: F - Finite lattice containing 28 elements - sage: G = F.relabel(C.face_lattice_facet_repr) - sage: G._elements - ((An inequality (0, 0, -1) x + 1 >= 0, - An inequality (0, -1, 0) x + 1 >= 0, - An inequality (-1, 0, 0) x + 1 >= 0, - An inequality (1, 0, 0) x + 1 >= 0, - An inequality (0, 0, 1) x + 1 >= 0, - An inequality (0, 1, 0) x + 1 >= 0), - (An inequality (0, 0, -1) x + 1 >= 0, - An inequality (0, -1, 0) x + 1 >= 0, - An inequality (1, 0, 0) x + 1 >= 0), - (An inequality (0, 0, -1) x + 1 >= 0, - An inequality (1, 0, 0) x + 1 >= 0, - An inequality (0, 1, 0) x + 1 >= 0), - (An inequality (0, 0, -1) x + 1 >= 0, An inequality (1, 0, 0) x + 1 >= 0), - (An inequality (1, 0, 0) x + 1 >= 0, - An inequality (0, 0, 1) x + 1 >= 0, - An inequality (0, 1, 0) x + 1 >= 0), - (An inequality (1, 0, 0) x + 1 >= 0, An inequality (0, 1, 0) x + 1 >= 0), - (An inequality (0, 0, -1) x + 1 >= 0, - An inequality (0, -1, 0) x + 1 >= 0, - An inequality (-1, 0, 0) x + 1 >= 0), - (An inequality (0, 0, -1) x + 1 >= 0, An inequality (0, -1, 0) x + 1 >= 0), - (An inequality (0, 0, -1) x + 1 >= 0, - An inequality (-1, 0, 0) x + 1 >= 0, - An inequality (0, 1, 0) x + 1 >= 0), - (An inequality (0, 0, -1) x + 1 >= 0, An inequality (0, 1, 0) x + 1 >= 0), - (An inequality (0, 0, -1) x + 1 >= 0, An inequality (-1, 0, 0) x + 1 >= 0), - (An inequality (0, 0, -1) x + 1 >= 0,), - (An inequality (0, -1, 0) x + 1 >= 0, - An inequality (1, 0, 0) x + 1 >= 0, - An inequality (0, 0, 1) x + 1 >= 0), - (An inequality (1, 0, 0) x + 1 >= 0, An inequality (0, 0, 1) x + 1 >= 0), - (An inequality (0, -1, 0) x + 1 >= 0, An inequality (1, 0, 0) x + 1 >= 0), - (An inequality (1, 0, 0) x + 1 >= 0,), - (An inequality (0, -1, 0) x + 1 >= 0, - An inequality (-1, 0, 0) x + 1 >= 0, - An inequality (0, 0, 1) x + 1 >= 0), - (An inequality (0, -1, 0) x + 1 >= 0, An inequality (0, 0, 1) x + 1 >= 0), - (An inequality (0, -1, 0) x + 1 >= 0, An inequality (-1, 0, 0) x + 1 >= 0), - (An inequality (0, -1, 0) x + 1 >= 0,), - (An inequality (-1, 0, 0) x + 1 >= 0, - An inequality (0, 0, 1) x + 1 >= 0, - An inequality (0, 1, 0) x + 1 >= 0), - (An inequality (-1, 0, 0) x + 1 >= 0, An inequality (0, 1, 0) x + 1 >= 0), - (An inequality (0, 0, 1) x + 1 >= 0, An inequality (0, 1, 0) x + 1 >= 0), - (An inequality (0, 1, 0) x + 1 >= 0,), - (An inequality (-1, 0, 0) x + 1 >= 0, An inequality (0, 0, 1) x + 1 >= 0), - (An inequality (0, 0, 1) x + 1 >= 0,), - (An inequality (-1, 0, 0) x + 1 >= 0,), - ()) - - sage: P = Polyhedron(rays=[[0,1], [1,0]], vertices=[[0,1], [1,0]]) - sage: C = CombinatorialPolyhedron(P) - sage: F = C.face_lattice() - sage: G = F.relabel(C.face_lattice_facet_repr) - sage: G._elements - ((An inequality (1, 0) x + 0 >= 0, - An inequality (0, 1) x + 0 >= 0, - An inequality (1, 1) x - 1 >= 0), - (An inequality (1, 0) x + 0 >= 0, An inequality (1, 1) x - 1 >= 0), - (An inequality (1, 0) x + 0 >= 0,), - (An inequality (0, 1) x + 0 >= 0, An inequality (1, 1) x - 1 >= 0), - (An inequality (0, 1) x + 0 >= 0,), - (An inequality (1, 1) x - 1 >= 0,), - ()) - - sage: def f(i): return C.face_lattice_facet_repr(i, False) + sage: def f(i): return C.face_by_face_lattice_index(i).Vrepr(False) sage: G = F.relabel(f) sage: G._elements - ((0, 1, 2), (0, 2), (1, 2), (1,), (2,), (0,), ()) + ((), (0,), (0, 1), (0, 2), (0, 1, 2)) """ self._record_all_faces() # Initalize ``_all_faces``, if not done yet. - dim = self.face_lattice_dimension(index) # Determine dimension to that index. + dim = self._face_lattice_dimension(index) # Determine dimension to that index. newindex = index - sum(self._f_vector[:dim + 1]) # Index in that level-set. - # Let ``_all_faces`` determine facet-representation. - return self._all_faces.facet_repr(dim, newindex, names=names) + # Let ``_all_faces`` determine Vrepresentation. + return self._all_faces.get_face(dim, newindex) cdef int _compute_f_vector(self) except -1: r""" @@ -1617,7 +1495,7 @@ cdef class CombinatorialPolyhedron(SageObject): return 0 # There is no need to recompute the f_vector. cdef bint dual - if self._unbounded or self._nr_facets <= self._length_Vrep: + if self._unbounded or self._n_facets <= self._length_Vrepr: # In this case the non-dual approach is faster.. dual = False else: @@ -1636,12 +1514,12 @@ cdef class CombinatorialPolyhedron(SageObject): # For each face in the iterator, add `1` to the corresponding entry in # ``f_vector``. - if self._nr_facets > 0 and dim > 0: - d = face_iter.next_face() + if self._n_facets > 0 and dim > 0: + d = face_iter.next_dimension() while (d < dim): sig_check() f_vector[d+1] += 1 - d = face_iter.next_face() + d = face_iter.next_dimension() # Copy ``f_vector``. if dual: @@ -1697,13 +1575,13 @@ cdef class CombinatorialPolyhedron(SageObject): if dual: # We have actually computed the ridges. sig_block() - self._nr_ridges = counter + self._n_ridges = counter self._ridges = edges self._mem_tuple += (mem,) sig_unblock() else: sig_block() - self._nr_edges = counter + self._n_edges = counter self._edges = edges self._mem_tuple += (mem,) sig_unblock() @@ -1718,13 +1596,13 @@ cdef class CombinatorialPolyhedron(SageObject): if dual: # We have actually computed the ridges. sig_block() - self._nr_ridges = counter + self._n_ridges = counter self._ridges = edges self._mem_tuple += (mem,) sig_unblock() else: sig_block() - self._nr_edges = counter + self._n_edges = counter self._edges = edges self._mem_tuple += (mem,) sig_unblock() @@ -1741,10 +1619,10 @@ cdef class CombinatorialPolyhedron(SageObject): # requires the dimension of the original polyhedron face_iter = self._face_iter(dual, dim - 2) - if self._nr_facets > 0 and dim > 0: + if self._n_facets > 0 and dim > 0: # If not, there won't even be any edges. Prevent error message. - while (face_iter.next_face() == 1): + while (face_iter.next_dimension() == 1): # Determine the position in ``edges``. one = counter // len_edge_list @@ -1770,13 +1648,13 @@ cdef class CombinatorialPolyhedron(SageObject): # Success, copy the data to ``CombinatorialPolyhedron``. if dual: sig_block() - self._nr_ridges = counter + self._n_ridges = counter self._ridges = edges self._mem_tuple += (mem,) sig_unblock() else: sig_block() - self._nr_edges = counter + self._n_edges = counter self._edges = edges self._mem_tuple += (mem,) sig_unblock() @@ -1788,10 +1666,10 @@ cdef class CombinatorialPolyhedron(SageObject): f_vector[dim + 1] = 1 # This is not a proper face. counter = 0 - if self._nr_facets > 0 and dim > 0: + if self._n_facets > 0 and dim > 0: # If not, there won't even be any edges. Prevent error message. - d = face_iter.next_face() + d = face_iter.next_dimension() while (d < dim): f_vector[d+1] += 1 @@ -1819,14 +1697,14 @@ cdef class CombinatorialPolyhedron(SageObject): edges[one][2*two + 1] = face_iter.atom_repr[1] counter += 1 - d = face_iter.next_face() # Go to next face. + d = face_iter.next_dimension() # Go to next face. # Success, copy the data to ``CombinatorialPolyhedron``. if dual: sig_block() self._f_vector = \ tuple(smallInteger(f_vector[dim+1-i]) for i in range(dim+2)) - self._nr_ridges = counter + self._n_ridges = counter self._ridges = edges self._mem_tuple += (mem,) sig_unblock() @@ -1834,7 +1712,7 @@ cdef class CombinatorialPolyhedron(SageObject): sig_block() self._f_vector = \ tuple(smallInteger(f_vector[i]) for i in range(dim+2)) - self._nr_edges = counter + self._n_edges = counter self._edges = edges self._mem_tuple += (mem,) sig_unblock() @@ -1863,7 +1741,7 @@ cdef class CombinatorialPolyhedron(SageObject): cdef size_t counter = 0 # the number of ridges so far cdef size_t current_length = 1 # dynamically enlarge **ridges - if dim == 1 and self._nr_facets > 1: + if dim == 1 and self._n_facets > 1: # In this case there is a ridge, but its not a proper face. ridges[0] = mem.allocarray(2, sizeof(size_t)) ridges[0][0] = 0 @@ -1873,13 +1751,13 @@ cdef class CombinatorialPolyhedron(SageObject): # Success, copy the data to ``CombinatorialPolyhedron``. if not dual: sig_block() - self._nr_ridges = counter + self._n_ridges = counter self._ridges = ridges self._mem_tuple += (mem,) sig_unblock() else: sig_block() - self._nr_edges = counter + self._n_edges = counter self._edges = ridges self._mem_tuple += (mem,) sig_unblock() @@ -1892,13 +1770,13 @@ cdef class CombinatorialPolyhedron(SageObject): # Success, copy the data to ``CombinatorialPolyhedron``. if not dual: sig_block() - self._nr_ridges = counter + self._n_ridges = counter self._ridges = ridges self._mem_tuple += (mem,) sig_unblock() else: sig_block() - self._nr_edges = counter + self._n_edges = counter self._edges = ridges self._mem_tuple += (mem,) sig_unblock() @@ -1912,12 +1790,12 @@ cdef class CombinatorialPolyhedron(SageObject): else: face_iter = self._face_iter(dual, dim -2) - if self._nr_facets > 1 and dim > 0: + if self._n_facets > 1 and dim > 0: # If not, there won't even be any ridges # as intersection of two distince facets. # Prevent error message. - while (face_iter.next_face() == dim - 2): + while (face_iter.next_dimension() == dim - 2): # Determine the position in ``ridges``. one = counter // len_ridge_list @@ -1943,13 +1821,13 @@ cdef class CombinatorialPolyhedron(SageObject): # Success, copy the data to ``CombinatorialPolyhedron``. if not dual: sig_block() - self._nr_ridges = counter + self._n_ridges = counter self._ridges = ridges self._mem_tuple += (mem,) sig_unblock() else: sig_block() - self._nr_edges = counter + self._n_edges = counter self._edges = ridges self._mem_tuple += (mem,) sig_unblock() @@ -2003,7 +1881,7 @@ cdef class CombinatorialPolyhedron(SageObject): if dim > -1: while (f_vector[dimension_one + 1] == 0): # Taking care of cases, where there might be no faces - # of dimension 0, 1, etc (``self._nr_lines > 0``). + # of dimension 0, 1, etc (``self._n_lines > 0``). dimension_one += 1 dimension_two = -1 @@ -2053,7 +1931,7 @@ cdef class CombinatorialPolyhedron(SageObject): dimension_two = dimension_one - 1 # Success, copy the data to ``CombinatorialPolyhedron``. - self._nr_face_lattice_incidences = counter + self._n_face_lattice_incidences = counter sig_block() self._mem_tuple += (mem,) self._face_lattice_incidences = incidences @@ -2076,30 +1954,30 @@ cdef class CombinatorialPolyhedron(SageObject): sage: P = polytopes.permutahedron(4) sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter() - sage: tup = tuple((it.vertex_repr(),it.facet_repr()) for _ in it) + sage: tup = tuple((face.Vrepr(),face.Hrepr()) for face in it) sage: rg = range(1,sum(C.f_vector()) - 1) - sage: tup2 = tuple((C.face_lattice_vertex_repr(i), - ....: C.face_lattice_facet_repr(i)) for i in rg) + sage: tup2 = tuple((C.face_by_face_lattice_index(i).Vrepr(), + ....: C.face_by_face_lattice_index(i).Hrepr()) for i in rg) sage: sorted(tup) == sorted(tup2) True sage: P = polytopes.cyclic_polytope(4,10) sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter() - sage: tup = tuple((it.vertex_repr(),it.facet_repr()) for _ in it) + sage: tup = tuple((face.Vrepr(),face.Hrepr()) for face in it) sage: rg = range(1,sum(C.f_vector()) - 1) - sage: tup2 = tuple((C.face_lattice_vertex_repr(i), - ....: C.face_lattice_facet_repr(i)) for i in rg) + sage: tup2 = tuple((C.face_by_face_lattice_index(i).Vrepr(), + ....: C.face_by_face_lattice_index(i).Hrepr()) for i in rg) sage: sorted(tup) == sorted(tup2) True sage: P = Polyhedron(rays=[[1,0,0], [-1,0,0], [0,-1,0]]) sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter() - sage: tup = tuple((it.vertex_repr(),it.facet_repr()) for _ in it) + sage: tup = tuple((face.Vrepr(),face.Hrepr()) for face in it) sage: rg = range(1,sum(C.f_vector()) - 1) - sage: tup2 = tuple((C.face_lattice_vertex_repr(i), - ....: C.face_lattice_facet_repr(i)) for i in rg) + sage: tup2 = tuple((C.face_by_face_lattice_index(i).Vrepr(), + ....: C.face_by_face_lattice_index(i).Hrepr()) for i in rg) sage: sorted(tup) == sorted(tup2) True @@ -2107,10 +1985,10 @@ cdef class CombinatorialPolyhedron(SageObject): ....: [0,-1,0], [0,1,0]]) sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter() - sage: tup = tuple((it.vertex_repr(),it.facet_repr()) for _ in it) + sage: tup = tuple((face.Vrepr(),face.Hrepr()) for face in it) sage: rg = range(1,sum(C.f_vector()) - 1) - sage: tup2 = tuple((C.face_lattice_vertex_repr(i), - ....: C.face_lattice_facet_repr(i)) for i in rg) + sage: tup2 = tuple((C.face_by_face_lattice_index(i).Vrepr(), + ....: C.face_by_face_lattice_index(i).Hrepr()) for i in rg) sage: sorted(tup) == sorted(tup2) True """ diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/bit_vector_operations.cc b/src/sage/geometry/polyhedron/combinatorial_polyhedron/bit_vector_operations.cc index 9b98078d82f..96fd8c187a8 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/bit_vector_operations.cc +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/bit_vector_operations.cc @@ -67,19 +67,19 @@ inline size_t count_atoms(uint64_t* A, size_t face_length){ } size_t get_next_level(\ - uint64_t **faces, const size_t nr_faces, uint64_t **maybe_newfaces, \ + uint64_t **faces, const size_t n_faces, uint64_t **maybe_newfaces, \ uint64_t **newfaces, uint64_t **visited_all, \ - size_t nr_visited_all, size_t face_length){ + size_t n_visited_all, size_t face_length){ /* - Set ``newfaces`` to be the facets of ``faces[nr_faces -1]`` + Set ``newfaces`` to be the facets of ``faces[n_faces -1]`` that are not contained in a face of ``visited_all``. INPUT: - - ``maybe_newfaces`` -- quasi of type ``uint64_t[nr_faces -1][face_length]``, + - ``maybe_newfaces`` -- quasi of type ``uint64_t[n_faces -1][face_length]``, needs to be ``chunksize``-Bit aligned - - ``newfaces`` -- quasi of type ``*uint64_t[nr_faces -1] - - ``visited_all`` -- quasi of type ``*uint64_t[nr_visited_all] + - ``newfaces`` -- quasi of type ``*uint64_t[n_faces -1] + - ``visited_all`` -- quasi of type ``*uint64_t[n_visited_all] - ``face_length`` -- length of the faces OUTPUT: @@ -89,32 +89,32 @@ size_t get_next_level(\ ALGORITHM: - To get all facets of ``faces[nr_faces-1]``, we would have to: - - Intersect the first ``nr_faces-1`` faces of ``faces`` with the last face. + To get all facets of ``faces[n_faces-1]``, we would have to: + - Intersect the first ``n_faces-1`` faces of ``faces`` with the last face. - Add all the intersection of ``visited_all`` with the last face - Out of both the inclusion-maximal ones are of codimension one, i.e. facets. As we have visited all faces of ``visited_all``, we alter the algorithm to not revisit: - Step 1: Intersect the first ``nr_faces-1`` faces of ``faces`` with the last face. + Step 1: Intersect the first ``n_faces-1`` faces of ``faces`` with the last face. Step 2: Out of thosse the inclusion-maximal ones are some of the facets. At least we obtain all of those, that we have not already visited. Maybe, we get some more. Step 3: Only keep those that we have not already visited. - We obtain exactly the facets of ``faces[nr_faces-1]`` that we have + We obtain exactly the facets of ``faces[n_faces-1]`` that we have not visited yet. */ // Step 1: - for (size_t j = 0; j < nr_faces - 1; j++){ - intersection(faces[j], faces[nr_faces - 1], maybe_newfaces[j], face_length); + for (size_t j = 0; j < n_faces - 1; j++){ + intersection(faces[j], faces[n_faces - 1], maybe_newfaces[j], face_length); } // We keep track, which face in ``maybe_newfaces`` is a new face. - int *is_not_newface = new int[nr_faces -1](); + int *is_not_newface = new int[n_faces -1](); // For each face we will Step 2 and Step 3. - for (size_t j = 0; j < nr_faces-1; j++){ + for (size_t j = 0; j < n_faces-1; j++){ // Step 2a: for(size_t k = 0; k < j; k++){ // Testing if maybe_newfaces[j] is contained in different nextface. @@ -130,7 +130,7 @@ size_t get_next_level(\ } // Step 2b: - for(size_t k = j+1; k < nr_faces-1; k++){ + for(size_t k = j+1; k < n_faces-1; k++){ // Testing if maybe_newfaces[j] is contained in different nextface. if(is_subset(maybe_newfaces[j],maybe_newfaces[k], face_length)){ // If so, it is not inclusion-maximal and hence not of codimension 1. @@ -144,7 +144,7 @@ size_t get_next_level(\ } // Step 3: - for (size_t k = 0; k < nr_visited_all; k++){ + for (size_t k = 0; k < n_visited_all; k++){ // Testing if maybe_newfaces[j] is contained in one, // we have already completely visited. if(is_subset(maybe_newfaces[j], visited_all[k], face_length)){ @@ -156,31 +156,31 @@ size_t get_next_level(\ } // Set ``newfaces`` to point to the correct ones. - size_t nr_newfaces = 0; // length of newfaces2 - for (size_t j = 0; j < nr_faces -1; j++){ + size_t n_newfaces = 0; // length of newfaces2 + for (size_t j = 0; j < n_faces -1; j++){ if (is_not_newface[j]) { // Not a new face of codimension 1. continue; } // It is a new face of codimension 1. - newfaces[nr_newfaces] = maybe_newfaces[j]; - nr_newfaces++; + newfaces[n_newfaces] = maybe_newfaces[j]; + n_newfaces++; } delete[] is_not_newface; - return nr_newfaces; + return n_newfaces; } size_t bit_repr_to_coatom_repr(uint64_t *face, uint64_t **coatoms, \ - size_t nr_coatoms, size_t face_length, \ + size_t n_coatoms, size_t face_length, \ size_t *output){ /* Write the coatom-representation of face in output. Return length. ``face_length`` is the length of ``face`` and ``coatoms[i]`` in terms of uint64_t. - ``nr_coatoms`` length of ``coatoms``. + ``n_coatoms`` length of ``coatoms``. */ size_t count_length = 0; - for (size_t i = 0; i < nr_coatoms; i++){ + for (size_t i = 0; i < n_coatoms; i++){ if (is_subset(face, coatoms[i], face_length)){ // ``face`` is contain in ``coatoms[i]``, // then ``i`` is an element in the coatom-represention. diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/bit_vector_operations.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/bit_vector_operations.pxd index c46b19d71e4..e5533730820 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/bit_vector_operations.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/bit_vector_operations.pxd @@ -13,18 +13,18 @@ cdef extern from "bit_vector_operations.cc": # ``face_length`` is the length of A and B in terms of uint64_t. cdef size_t get_next_level( - uint64_t **faces, const size_t nr_faces, uint64_t **nextfaces, + uint64_t **faces, const size_t n_faces, uint64_t **nextfaces, uint64_t **nextfaces2, uint64_t **visited_all, - size_t nr_visited_all, size_t face_length) -# Set ``newfaces`` to be the facets of ``faces[nr_faces -1]`` + size_t n_visited_all, size_t face_length) +# Set ``newfaces`` to be the facets of ``faces[n_faces -1]`` # that are not contained in a face of ``visited_all``. # INPUT: -# - ``maybe_newfaces`` -- quasi of type ``uint64_t[nr_faces -1][face_length]``, +# - ``maybe_newfaces`` -- quasi of type ``uint64_t[n_faces -1][face_length]``, # needs to be ``chunksize``-Bit aligned -# - ``newfaces`` -- quasi of type ``*uint64_t[nr_faces -1] -# - ``visited_all`` -- quasi of type ``*uint64_t[nr_visited_all] +# - ``newfaces`` -- quasi of type ``*uint64_t[n_faces -1] +# - ``visited_all`` -- quasi of type ``*uint64_t[n_visited_all] # - ``face_length`` -- length of the faces # OUTPUT: @@ -34,19 +34,19 @@ cdef extern from "bit_vector_operations.cc": # ALGORITHM: -# To get all facets of ``faces[nr_faces-1]``, we would have to: -# - Intersect the first ``nr_faces-1`` faces of ``faces`` with the last face. +# To get all facets of ``faces[n_faces-1]``, we would have to: +# - Intersect the first ``n_faces-1`` faces of ``faces`` with the last face. # - Add all the intersection of ``visited_all`` with the last face # - Out of both the inclusion-maximal ones are of codimension 1, i.e. facets. # As we have visited all faces of ``visited_all``, we alter the algorithm # to not revisit: -# Step 1: Intersect the first ``nr_faces-1`` faces of ``faces`` with the last face. +# Step 1: Intersect the first ``n_faces-1`` faces of ``faces`` with the last face. # Step 2: Out of thosse the inclusion-maximal ones are some of the facets. # At least we obtain all of those, that we have not already visited. # Maybe, we get some more. # Step 3: Only keep those that we have not already visited. -# We obtain exactly the facets of ``faces[nr_faces-1]`` that we have +# We obtain exactly the facets of ``faces[n_faces-1]`` that we have # not visited yet. cdef size_t count_atoms(uint64_t *A, size_t face_length) @@ -55,9 +55,9 @@ cdef extern from "bit_vector_operations.cc": # ``face_length`` is the length of A in terms of uint64_t. cdef size_t bit_repr_to_coatom_repr( - uint64_t *face, uint64_t **coatoms, size_t nr_coatoms, + uint64_t *face, uint64_t **coatoms, size_t n_coatoms, size_t face_length, size_t *output) # Write the coatom-representation of face in output. Return length. # ``face_length`` is the length of ``face`` and ``coatoms[i]`` # in terms of uint64_t. -# ``nr_coatoms`` length of ``coatoms``. +# ``n_coatoms`` length of ``coatoms``. diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd new file mode 100644 index 00000000000..9372acae5c1 --- /dev/null +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd @@ -0,0 +1,29 @@ +cimport cython +from libc.stdint cimport uint64_t +from sage.ext.memory_allocator cimport MemoryAllocator +from sage.structure.sage_object cimport SageObject +from .list_of_faces cimport ListOfFaces +from .face_iterator cimport FaceIterator + +@cython.final +cdef class CombinatorialFace(SageObject): + cdef readonly bint _dual # if 1, then iterate over dual Polyhedron + cdef ListOfFaces face_mem # constructing face + cdef uint64_t *face # the face in bit-repr + + cdef MemoryAllocator _mem + cdef size_t *atom_repr # a place where atom-representaion of face will be stored + cdef size_t *coatom_repr # a place where coatom-representaion of face will be stored + cdef int _dimension # dimension of current face, dual dimension if ``dual`` + cdef int _ambient_dimension # dimension of the polyhedron + cdef size_t face_length # stores length of the faces in terms of uint64_t + cdef tuple _V, _H, _equalities # some copies from ``CombinatorialPolyhedron`` + cdef size_t _hash_index # an index to give different hashes for all faces of a Polyhedron + + # Atoms and coatoms are the vertices/facets of the Polyedron. + # If ``dual == 0``, then coatoms are facets, atoms vertices and vice versa. + cdef ListOfFaces atoms, coatoms + + cdef size_t length_atom_repr(self) except -1 + cdef size_t set_coatom_repr(self) except -1 + cdef size_t set_atom_repr(self) except -1 diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx new file mode 100644 index 00000000000..816e05a0ce1 --- /dev/null +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx @@ -0,0 +1,564 @@ +r""" +CombinatorialFace + +This module provides the combinatorical type of a polyhedral face. + +Terminology in this module: + +- Vrepr -- ``[vertices, rays, lines]`` of the polyhedron. +- Hrepr -- inequalities and equalities of the polyhedron. +- Facets -- facets of the polyhedron. +- Coatoms -- the faces from which all others are constructed in + the face iterator. This will be facets or Vrepr. + In non-dual mode, faces are constructed as + intersections of the facets. In dual mode, the are + constructed theoretically as joins of vertices. + The coatoms are reprsented as incidences with the + atoms they contain. +- Atoms -- facets or Vrepr depending on application of algorithm. + Atoms are reprsented as incidences of coatoms they + are contained in. + +- Vrepresentation -- represents a face by a list of Vrepr it contains. +- Hrepresentation -- represents a face by a list of Hrepr it is contained in. +- bit representation -- represents incidences as ``uint64_t``-array, where + each Bit represents one incidences. There might + be trailing zeros, to fit alignment-requirements. + In most instances, faces are represented by the + Bit-representation, where each bit corresponds to + an atom. + +EXAMPLES: + +Obtain a face from a face iterator:: + + sage: P = polytopes.cube() + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter() + sage: face = next(it); face + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron + +Obtain a face from a face lattice index: + + sage: P = polytopes.simplex(2) + sage: C = CombinatorialPolyhedron(P) + sage: sorted(C.face_lattice()._elements) + [0, 1, 2, 3, 4, 5, 6, 7] + sage: face = C.face_by_face_lattice_index(0); face + Combinatorial type of a -1-dimensional face of a 2-dimensional polyhedron + +Obtain further information regarding a face:: + + sage: P = polytopes.octahedron() + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter(2) + sage: face = next(it); face + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron + sage: face.Vrepr() + (A vertex at (0, 0, 1), A vertex at (0, 1, 0), A vertex at (1, 0, 0)) + sage: face.length_Vrepr() + 3 + sage: face.Hrepr(names=False) + (5,) + sage: face.dimension() + 2 + sage: face.ambient_dimension() + 3 + +.. SEEALSO:: + + :class:`sage.geometry.polyhedron.combinatorial_polyhedron.base.CombinatorialPolyhedron`. + +AUTHOR: + +- Jonathan Kliem (2019-05) +""" + +#***************************************************************************** +# Copyright (C) 2019 Jonathan Kliem +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from __future__ import absolute_import, division, print_function + +import numbers +from sage.rings.integer cimport smallInteger, +from .conversions cimport bit_repr_to_Vrepr_list +from .base cimport CombinatorialPolyhedron +from .bit_vector_operations cimport count_atoms, bit_repr_to_coatom_repr +from .list_of_all_faces cimport ListOfAllFaces +from libc.string cimport memcpy + +cdef extern from "Python.h": + int unlikely(int) nogil # Defined by Cython + +cdef class CombinatorialFace(SageObject): + r""" + A class of the combinatorial type of a polyhedral face. + + EXAMPLES: + + Obtain a combinatorial face from a face iterator:: + + sage: P = polytopes.cyclic_polytope(5,8) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter() + sage: next(it) + Combinatorial type of a 0-dimensional face of a 5-dimensional polyhedron + + Obtain a combinatorial face from an index of the face lattice:: + + sage: F = C.face_lattice() + sage: F._elements[3] + 29 + sage: C.face_by_face_lattice_index(29) + Combinatorial type of a 1-dimensional face of a 5-dimensional polyhedron + + Obtain the dimension of a combinatorial face:: + + sage: face = next(it) + sage: face.dimension() + 0 + + The dimension of the polyhedron:: + + sage: face.ambient_dimension() + 5 + + The Vrepresentation:: + + sage: face.Vrepr() + (A vertex at (6, 36, 216, 1296, 7776),) + sage: face.Vrepr(names=False) + (6,) + sage: face.length_Vrepr() + 1 + + The Hrepresentation:: + + sage: face.Hrepr() + (An inequality (60, -112, 65, -14, 1) x + 0 >= 0, + An inequality (180, -216, 91, -16, 1) x + 0 >= 0, + An inequality (360, -342, 119, -18, 1) x + 0 >= 0, + An inequality (840, -638, 179, -22, 1) x + 0 >= 0, + An inequality (-2754, 1175, -245, 25, -1) x + 2520 >= 0, + An inequality (504, -450, 145, -20, 1) x + 0 >= 0, + An inequality (-1692, 853, -203, 23, -1) x + 1260 >= 0, + An inequality (252, -288, 113, -18, 1) x + 0 >= 0, + An inequality (-844, 567, -163, 21, -1) x + 420 >= 0, + An inequality (84, -152, 83, -16, 1) x + 0 >= 0, + An inequality (-210, 317, -125, 19, -1) x + 0 >= 0) + sage: face.Hrepr(names=False) + (3, 4, 5, 6, 7, 8, 9, 10, 11, 18, 19) + sage: face.length_Hrepr() + 11 + """ + def __init__(self, data, dimension=None, index=None): + r""" + Initialize :class:`CombinatorialFace`. + + See :class:`CombinatorialFace`. + + TESTS:: + + sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3], + ....: [0,2,3],[1,2,3]]) + sage: it = C.face_iter() + sage: next(it) # indirect doctest + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron + + sage: C.face_by_face_lattice_index(0) + Combinatorial type of a -1-dimensional face of a 3-dimensional polyhedron + + sage: TestSuite(sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face.CombinatorialFace).run() + """ + cdef FaceIterator it + cdef ListOfAllFaces all_faces + + if isinstance(data, FaceIterator): + assert dimension is None and index is None, "dimension and index must be ``None``, when providing a face iterator" + + # Copy data from FaceIterator. + it = data + self._dual = it.dual + self.face_mem = ListOfFaces(1, it.face_length*64) + self.face = self.face_mem.data[0] + memcpy(self.face, it.face, it.face_length*8) + self._mem = MemoryAllocator() + self._dimension = it.current_dimension + self._ambient_dimension = it.dimension + self.face_length = it.face_length + self._V = it._V + self._H = it._H + self._equalities = it._equalities + self.atoms = it.atoms + self.coatoms = it.coatoms + self._hash_index = it._index + + elif isinstance(data, ListOfAllFaces): + assert isinstance(dimension,numbers.integral), "dimension must be an integer" + assert isinstance(index, numbers.integral), "index must be an integer" + assert -1 <= dimension <= all_faces.dimension, "dimension must be a face dimension of the polyhedron" + assert 0 <= index < all_faces.f_vector[dimension + 1], "index is out of range" + + # Copy data from ListOfAllFaces. + all_faces = data + self._dual = all_faces.dual + self.face_mem = ListOfFaces(1, all_faces.face_length*64) + self.face = self.face_mem.data[0] + memcpy(self.face, all_faces.faces[dimension+1][index], all_faces.face_length*8) + self._mem = MemoryAllocator() + self._dimension = dimension + self._ambient_dimension = all_faces.dimension + self.face_length = all_faces.face_length + self._V = all_faces._V + self._H = all_faces._H + self._equalities = all_faces._equalities + self.atoms = all_faces.atoms + self.coatoms = all_faces.coatoms + + self._hash_index = index + for i in range(-1,dimension): + self._hash_index += all_faces.f_vector[i+1] + else: + raise NotImplementedError("data must be face iterator or a list of all faces") + + def _repr_(self): + r""" + Return a description of the combinatorial face. + + EXAMPLES:: + + sage: P = polytopes.permutahedron(6) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter(dimension=3, dual=False) + sage: face = next(it) + sage: face.__repr__() + 'Combinatorial type of a 3-dimensional face of a 5-dimensional polyhedron' + sage: it = C.face_iter(dimension=3, dual=True) + sage: face = next(it) + sage: face.__repr__() + 'Combinatorial type of a 3-dimensional face of a 5-dimensional polyhedron' + """ + return "Combinatorial type of a {}-dimensional face of a {}-dimensional polyhedron".format(self.dimension(), self.ambient_dimension()) + + def __reduce__(self): + r""" + Override __reduce__ to indicate that pickle/unpickle will not work. + + EXAMPLES:: + + sage: P = polytopes.simplex() + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter() + sage: face = next(it) + sage: face1 = loads(face.dumps()) + Traceback (most recent call last): + ... + NotImplementedError + """ + raise NotImplementedError + + def __hash__(self): + r""" + Return an index for the face. + + If the face was constructed from a :class:`sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator`, + then this is the index of the occurence in the iterator. + + If the face was constructed from + :meth:`sage:geometry.polyhedron.combinatorial_polyhedronn.base.CombinatorialPolyhedron.face_by_face_lattice_index`, + then this the index in the level set plus the number of lower dimension (or higher dimension). + + EXAMPLES:: + + sage: P = polytopes.simplex(2) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter() + sage: [hash(face) for face in it] + [1, 2, 3, 4, 5, 6] + + TESTS:: + + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: F = C.face_lattice() + sage: G = F.relabel(C.face_by_face_lattice_index) + + sage: P = polytopes.cyclic_polytope(4,10) + sage: C = CombinatorialPolyhedron(P) + sage: F = C.face_lattice() + sage: G = F.relabel(C.face_by_face_lattice_index) + """ + return self._hash_index + + def dimension(self): + r""" + Return the dimension of the face. + + EXAMPLES:: + + sage: P = polytopes.associahedron(['A', 3]) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter() + sage: face = next(it) + sage: face.dimension() + 2 + """ + if self._dual: + return smallInteger(self._ambient_dimension - self._dimension - 1) + else: + return smallInteger(self._dimension) + + def ambient_dimension(self): + r""" + Return the dimension of the polyhedron. + + EXAMPLES:: + + sage: P = polytopes.cube() + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter() + sage: face = next(it) + sage: face.ambient_dimension() + 3 + """ + return smallInteger(self._ambient_dimension) + + def Vrepr(self, names=True): + r""" + Return the vertex-representation of the current face. + + The vertex-representation consists of + the ``[vertices, rays, lines]`` that face contains. + + INPUT: + + - ``names`` -- if ``True`` returns the names of the ``[vertices, rays, lines]`` + as given on initialization of the :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.base.CombinatorialPolyhedron` + + EXAMPLES:: + + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter(dimension=2) + sage: face = next(it) + sage: face.Vrepr() + (A vertex at (4, 1, 5, 2, 3), + A vertex at (4, 2, 5, 1, 3), + A vertex at (5, 1, 4, 2, 3), + A vertex at (5, 2, 4, 1, 3)) + sage: face = next(it) + sage: face.Vrepr() + (A vertex at (4, 1, 5, 2, 3), + A vertex at (4, 1, 5, 3, 2), + A vertex at (5, 1, 4, 2, 3), + A vertex at (5, 1, 4, 3, 2)) + sage: next(it).Vrepr(False) + (76, 77, 82, 83, 88, 89) + sage: next(it).Vrepr(False) + (77, 83, 101, 107) + + sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3],[0,2,3],[1,2,3]]) + sage: it = C.face_iter() + sage: for face in it: (face.dimension(), face.Vrepr()) + (2, (1, 2, 3)) + (2, (0, 2, 3)) + (2, (0, 1, 3)) + (2, (0, 1, 2)) + (1, (2, 3)) + (1, (1, 3)) + (1, (1, 2)) + (0, (3,)) + (0, (2,)) + (0, (1,)) + (1, (0, 3)) + (1, (0, 2)) + (0, (0,)) + (1, (0, 1)) + """ + cdef size_t length + if self._dual: + # if dual, the Vrepresenation corresponds to the coatom-representation + length = self.set_coatom_repr() + if names and self._V: + return tuple(self._V[self.coatom_repr[i]] + for i in range(length)) + else: + return tuple(smallInteger(self.coatom_repr[i]) + for i in range(length)) + else: + # if not dual, the Vrepresenation corresponds to the atom-representation + length = self.set_atom_repr() + if names and self._V: + return tuple(self._V[self.atom_repr[i]] + for i in range(length)) + else: + return tuple(smallInteger(self.atom_repr[i]) + for i in range(length)) + + def length_Vrepr(self): + r""" + Return the length of the face. + + Might be faster than `len(self.Vrepr())`. + + EXAMPLES:: + + sage: P = polytopes.cube() + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter() + sage: all(face.length_Vrepr() == len(face.Vrepr()) for face in it) + True + """ + if self._dual: + return smallInteger(self.set_coatom_repr()) + else: + return smallInteger(self.length_atom_repr()) + + def Hrepr(self, names=True): + r""" + Return the Hrepresentation of the face. + + If ``names`` is ``False`` this is just the indices + of the facets the face is contained in. + If ``names`` is ``True`` this the defining facets + and equations of the face. + + The facet-representation consists of the facets + that contain the face and of the equalities of the polyhedron. + + INPUT: + + - ``names`` -- if ``True`` returns the names of the ``[facets, equations]`` + as given on initialization of :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.base.CombinatorialPolyhedron` + + EXAMPLES:: + + sage: P = polytopes.permutahedron(5) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter(2) + sage: next(it).Hrepr() + (An inequality (0, 1, 0, 1, 0) x - 3 >= 0, + An inequality (0, 1, 0, 1, 1) x - 6 >= 0, + An equation (1, 1, 1, 1, 1) x - 15 == 0) + sage: next(it).Hrepr() + (An inequality (0, 1, 0, 0, 0) x - 1 >= 0, + An inequality (0, 1, 0, 1, 1) x - 6 >= 0, + An equation (1, 1, 1, 1, 1) x - 15 == 0) + sage: next(it).Hrepr(False) + (12, 29) + sage: next(it).Hrepr(False) + (6, 29) + + sage: P = polytopes.cyclic_polytope(4,6) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter() + sage: next(it).Hrepr() + (An inequality (-20, 29, -10, 1) x + 0 >= 0, + An inequality (60, -47, 12, -1) x + 0 >= 0, + An inequality (30, -31, 10, -1) x + 0 >= 0, + An inequality (10, -17, 8, -1) x + 0 >= 0, + An inequality (-154, 71, -14, 1) x + 120 >= 0, + An inequality (-78, 49, -12, 1) x + 40 >= 0) + sage: next(it).Hrepr() + (An inequality (-50, 35, -10, 1) x + 24 >= 0, + An inequality (-12, 19, -8, 1) x + 0 >= 0, + An inequality (-20, 29, -10, 1) x + 0 >= 0, + An inequality (60, -47, 12, -1) x + 0 >= 0, + An inequality (-154, 71, -14, 1) x + 120 >= 0, + An inequality (-78, 49, -12, 1) x + 40 >= 0) + sage: next(it).Hrepr(False) + (0, 1, 2, 4, 5, 7) + sage: next(it).Hrepr(False) + (0, 1, 5, 6, 7, 8) + sage: next(it).Hrepr(False) + (0, 1, 2, 3, 6, 8) + sage: [next(it).dimension() for _ in range(2)] + [0, 1] + sage: face = next(it) + sage: face.Hrepr(False) + (4, 5, 7) + sage: face.Hrepr() + (An inequality (60, -47, 12, -1) x + 0 >= 0, + An inequality (30, -31, 10, -1) x + 0 >= 0, + An inequality (-154, 71, -14, 1) x + 120 >= 0) + """ + cdef size_t length + if not self._dual: + # if not dual, the facet-represention corresponds to the coatom-representation + length = self.set_coatom_repr() # fill self.coatom_repr_face + if names and self._H: + return tuple(self._H[self.coatom_repr[i]] + for i in range(length)) + self._equalities + else: + return tuple(smallInteger(self.coatom_repr[i]) + for i in range(length)) + else: + # if dual, the facet-represention corresponds to the atom-representation + length = self.set_atom_repr() # fill self.atom_repr_face + if names and self._H: + return tuple(self._H[self.atom_repr[i]] + for i in range(length)) + self._equalities + else: + return tuple(smallInteger(self.atom_repr[i]) + for i in range(length)) + + def length_Hrepr(self): + r""" + Returns the length of the :meth:`Hrepr`. + + Might be faster than ``len(self.Hrepr())``. + + EXAMPLES:: + + sage: P = polytopes.cube() + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter() + sage: all(face.length_Hrepr() == len(face.Hrepr()) for face in it) + True + """ + if not self._dual: + return smallInteger(self.set_coatom_repr()) + else: + return smallInteger(self.length_atom_repr()) + + cdef size_t length_atom_repr(self) except -1: + r""" + Compute the number of atoms in the current face by counting the + number of set bits. + """ + if self.face: + return count_atoms(self.face, self.face_length) + + # The face was not initialized properly. + raise LookupError("``FaceIterator`` does not point to a face") + + cdef size_t set_coatom_repr(self) except -1: + r""" + Set ``coatom_repr`` to be the coatom-representation of the current face. + Return its length. + """ + cdef size_t n_coatoms = self.coatoms.n_faces + cdef uint64_t **coatoms = self.coatoms.data + cdef size_t face_length = self.face_length + if not self.coatom_repr: + self.coatom_repr = self._mem.allocarray(self.coatoms.n_faces, sizeof(size_t)) + return bit_repr_to_coatom_repr(self.face, coatoms, n_coatoms, + face_length, self.coatom_repr) + + cdef size_t set_atom_repr(self) except -1: + r""" + Set ``atom_repr`` to be the atom-representation of the current face. + Return its length. + """ + cdef size_t face_length = self.face_length + if not self.atom_repr: + self.atom_repr = self._mem.allocarray(self.coatoms.n_atoms, sizeof(size_t)) + return bit_repr_to_Vrepr_list(self.face, self.atom_repr, face_length) + diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd index 3a579055e8a..7ba717c3736 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pxd @@ -1,10 +1,10 @@ from libc.stdint cimport uint64_t -cdef int vertex_list_to_bit_repr(tuple vertex_list, uint64_t *output, +cdef int Vrepr_list_to_bit_repr(tuple Vrepr_list, uint64_t *output, size_t face_length) except -1 cdef int incidences_to_bit_repr(tuple incidences, uint64_t *output, size_t face_length) except -1 -cdef size_t bit_repr_to_vertex_list(uint64_t *face, size_t *output, +cdef size_t bit_repr_to_Vrepr_list(uint64_t *face, size_t *output, size_t face_length) except -1 diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx index 09a920593d4..e3ef2ece7f1 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx @@ -27,13 +27,13 @@ Obtain the facets of a polyhedron as :class:`~sage.geometry.polyhedron.combinato sage: face_list.compute_dimension() 4 -Obtain the vertices of a polyhedron as facet-incidences stored in +Obtain the Vrepresentation of a polyhedron as facet-incidences stored in :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces`:: sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: import incidence_matrix_to_bit_repr_of_vertices + ....: import incidence_matrix_to_bit_repr_of_Vrepr sage: P = polytopes.associahedron(['A',4]) - sage: face_list = incidence_matrix_to_bit_repr_of_vertices(P.incidence_matrix()) + sage: face_list = incidence_matrix_to_bit_repr_of_Vrepr(P.incidence_matrix()) sage: face_list.compute_dimension() 4 @@ -44,12 +44,12 @@ Obtain the facets of a polyhedron as :class:`~sage.geometry.polyhedron.combinato sage: facets = ((0,1,2), (0,1,3), (0,2,3), (1,2,3)) sage: face_list = facets_tuple_to_bit_repr_of_facets(facets, 4) -Likewise for the vertices as facet-incidences:: +Likewise for the Vrepr as facet-incidences:: sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: import facets_tuple_to_bit_repr_of_vertices + ....: import facets_tuple_to_bit_repr_of_Vrepr sage: facets = ((0,1,2), (0,1,3), (0,2,3), (1,2,3)) - sage: face_list = facets_tuple_to_bit_repr_of_vertices(facets, 4) + sage: face_list = facets_tuple_to_bit_repr_of_Vrepr(facets, 4) AUTHOR: @@ -83,7 +83,7 @@ cdef inline uint64_t vertex_to_bit_dictionary(size_t i): """ return (1) << (64 - i - 1) -cdef int vertex_list_to_bit_repr(tuple vertex_list, uint64_t *output, +cdef int Vrepr_list_to_bit_repr(tuple Vrepr_list, uint64_t *output, size_t face_length) except -1: r""" Convert a vertex list into Bit-representation. Store it in ``output``. @@ -107,38 +107,38 @@ cdef int vertex_list_to_bit_repr(tuple vertex_list, uint64_t *output, sage: cython(''' ....: from libc.stdint cimport uint64_t ....: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: cimport vertex_list_to_bit_repr + ....: cimport Vrepr_list_to_bit_repr ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: from sage.rings.integer cimport smallInteger ....: - ....: def vertex_list_to_bit_repr_wrapper(tup): + ....: def Vrepr_list_to_bit_repr_wrapper(tup): ....: cdef size_t face_length = max(tup)//64 + 1 ....: cdef MemoryAllocator mem = MemoryAllocator() ....: cdef uint64_t *output = mem.allocarray(face_length, 8) - ....: vertex_list_to_bit_repr(tup, output, face_length) + ....: Vrepr_list_to_bit_repr(tup, output, face_length) ....: return tuple(smallInteger(output[i]) for i in range(face_length)) ....: - ....: def vertex_list_to_bit_repr_wrong_size(tup): + ....: def Vrepr_list_to_bit_repr_wrong_size(tup): ....: cdef size_t face_length = 1 ....: cdef MemoryAllocator mem = MemoryAllocator() ....: cdef uint64_t *output = mem.allocarray(face_length, 8) - ....: vertex_list_to_bit_repr(tup, output, face_length) + ....: Vrepr_list_to_bit_repr(tup, output, face_length) ....: return tuple(smallInteger(output[i]) for i in range(face_length)) ....: ''') # long time - sage: vertex_list_to_bit_repr_wrapper((62, 63)) # long time + sage: Vrepr_list_to_bit_repr_wrapper((62, 63)) # long time (3,) - sage: vertex_list_to_bit_repr_wrapper((61, 63, 125)) # long time + sage: Vrepr_list_to_bit_repr_wrapper((61, 63, 125)) # long time (5, 4) - sage: vertex_list_to_bit_repr_wrong_size((62, 70)) # long time + sage: Vrepr_list_to_bit_repr_wrong_size((62, 70)) # long time Traceback (most recent call last): ... IndexError: output too small to represent 70 - sage: vertex_list_to_bit_repr_wrapper((-1, 12)) # long time + sage: Vrepr_list_to_bit_repr_wrapper((-1, 12)) # long time Traceback (most recent call last): ... OverflowError: can't convert negative value to size_t - sage: vertex_list_to_bit_repr_wrapper((0, 0)) # long time + sage: Vrepr_list_to_bit_repr_wrapper((0, 0)) # long time Traceback (most recent call last): ... ValueError: entries of ``tup`` are not distinct @@ -148,9 +148,9 @@ cdef int vertex_list_to_bit_repr(tuple vertex_list, uint64_t *output, cdef size_t value # determines which bit will be set in output[position] memset(output, 0, face_length*8) # initialize output - if unlikely(len(vertex_list) != len(set(vertex_list))): + if unlikely(len(Vrepr_list) != len(set(Vrepr_list))): raise ValueError("entries of ``tup`` are not distinct") - for entry in vertex_list: + for entry in Vrepr_list: value = entry % 64 position = entry//64 if unlikely(position >= face_length): @@ -225,7 +225,7 @@ cdef int incidences_to_bit_repr(tuple incidences, uint64_t *output, raise IndexError("output too small to represent all incidences") for entry in range(length): if incidences[entry]: - # vertex ``entry`` is contained in the face, so set the corresponding bit + # Vrepr ``entry`` is contained in the face, so set the corresponding bit value = entry % 64 position = entry//64 output[position] += vertex_to_bit_dictionary(value) @@ -249,33 +249,33 @@ def incidence_matrix_to_bit_repr_of_facets(matrix): ....: from sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces \ ....: cimport ListOfFaces ....: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: cimport bit_repr_to_vertex_list + ....: cimport bit_repr_to_Vrepr_list ....: from sage.rings.integer cimport smallInteger ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: from libc.stdint cimport uint64_t ....: - ....: def bit_repr_to_vertex_list_wrapper(list_of_faces, index): + ....: def bit_repr_to_Vrepr_list_wrapper(list_of_faces, index): ....: cdef MemoryAllocator mem = MemoryAllocator() ....: cdef size_t *output ....: cdef ListOfFaces faces = list_of_faces - ....: output = mem.allocarray(faces.nr_vertices, + ....: output = mem.allocarray(faces.n_atoms, ....: sizeof(size_t)) ....: cdef uint64_t * data = faces.data[index] - ....: length = bit_repr_to_vertex_list( + ....: length = bit_repr_to_Vrepr_list( ....: data, output, faces.face_length) ....: return tuple(smallInteger(output[i]) for i in range(length)) - ....: ''') + ....: ''') # long time sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ ....: import incidence_matrix_to_bit_repr_of_facets sage: P = polytopes.permutahedron(4) sage: facets = incidence_matrix_to_bit_repr_of_facets(P.incidence_matrix()) - sage: facets.nr_faces + sage: facets.n_faces 14 - sage: facets.nr_vertices + sage: facets.n_atoms 24 - sage: for i in range(facets.nr_faces): - ....: print(bit_repr_to_vertex_list_wrapper(facets, i)) + sage: for i in range(facets.n_faces): + ....: print(bit_repr_to_Vrepr_list_wrapper(facets, i)) (18, 19, 20, 21, 22, 23) (9, 11, 15, 17, 21, 23) (16, 17, 22, 23) @@ -303,23 +303,23 @@ def incidence_matrix_to_bit_repr_of_facets(matrix): matrix = matrix[list(i for i in rg if not all(j for j in matrix[i]))] # Output will be a ``ListOfFaces`` with ``matrix.nrows()`` faces and - # ``matrix.ncols()`` vertices. + # ``matrix.ncols()`` Vrepr. cdef size_t length = matrix.nrows() cdef ListOfFaces facets = ListOfFaces(length, matrix.ncols()) cdef uint64_t **facets_data = facets.data cdef size_t i for i in range(length): - # Filling each facet with its vertex-incidences, which "is" the + # Filling each facet with its Vrepr-incidences, which "is" the # "i-th column" of the original matrix (but we have transposed). incidences_to_bit_repr(tuple(matrix[i]), facets_data[i], facets.face_length) return facets -def incidence_matrix_to_bit_repr_of_vertices(matrix): +def incidence_matrix_to_bit_repr_of_Vrepr(matrix): r""" - Initialize vertices in Bit-representation as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces`. + Initialize Vrepresentatives in Bit-representation as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces`. - Each vertex is represented as the facets it is contained in. + Each Vrepresenative is represented as the facets it is contained in. Those are the facets of the polar polyhedron, if it exists. INPUT: @@ -337,33 +337,33 @@ def incidence_matrix_to_bit_repr_of_vertices(matrix): ....: from sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces \ ....: cimport ListOfFaces ....: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: cimport bit_repr_to_vertex_list + ....: cimport bit_repr_to_Vrepr_list ....: from sage.rings.integer cimport smallInteger ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: from libc.stdint cimport uint64_t ....: - ....: def bit_repr_to_vertex_list_wrapper(list_of_faces, index): + ....: def bit_repr_to_Vrepr_list_wrapper(list_of_faces, index): ....: cdef MemoryAllocator mem = MemoryAllocator() ....: cdef size_t *output ....: cdef ListOfFaces faces = list_of_faces - ....: output = mem.allocarray(faces.nr_vertices, + ....: output = mem.allocarray(faces.n_atoms, ....: sizeof(size_t)) ....: cdef uint64_t * data = faces.data[index] - ....: length = bit_repr_to_vertex_list( + ....: length = bit_repr_to_Vrepr_list( ....: data, output, faces.face_length) ....: return tuple(smallInteger(output[i]) for i in range(length)) ....: ''') sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: import incidence_matrix_to_bit_repr_of_vertices + ....: import incidence_matrix_to_bit_repr_of_Vrepr sage: P = polytopes.permutahedron(4) - sage: vertices = incidence_matrix_to_bit_repr_of_vertices(P.incidence_matrix()) - sage: vertices.nr_faces + sage: vertices = incidence_matrix_to_bit_repr_of_Vrepr(P.incidence_matrix()) + sage: vertices.n_faces 24 - sage: vertices.nr_vertices + sage: vertices.n_atoms 14 - sage: for i in range(vertices.nr_faces): - ....: print(bit_repr_to_vertex_list_wrapper(vertices, i)) + sage: for i in range(vertices.n_faces): + ....: print(bit_repr_to_Vrepr_list_wrapper(vertices, i)) (3, 5, 9) (3, 5, 8) (3, 4, 9) @@ -400,27 +400,27 @@ def incidence_matrix_to_bit_repr_of_vertices(matrix): matrix = matrix[list(i for i in rg if not all(j for j in matrix[i]))] # Output will be a ``ListOfFaces`` with ``matrix.ncols()`` faces and - # ``matrix.nrows()`` vertices. + # ``matrix.nrows()`` Vrepr. cdef size_t length = matrix.ncols() - cdef ListOfFaces vertices = ListOfFaces(length, matrix.nrows()) - cdef uint64_t **vertices_data = vertices.data + cdef ListOfFaces Vrepr = ListOfFaces(length, matrix.nrows()) + cdef uint64_t **Vrepr_data = Vrepr.data cdef size_t i for i in range(length): - # Filling each facet with its vertex-incidences, which "is" the + # Filling each facet with its Vrepr-incidences, which "is" the # "i-th row" of the original matrix (but we have transposed). - incidences_to_bit_repr(tuple(matrix.column(i)), vertices_data[i], vertices.face_length) - return vertices + incidences_to_bit_repr(tuple(matrix.column(i)), Vrepr_data[i], Vrepr.face_length) + return Vrepr -def facets_tuple_to_bit_repr_of_facets(tuple facets_input, size_t nr_vertices): +def facets_tuple_to_bit_repr_of_facets(tuple facets_input, size_t n_Vrepr): r""" Initializes facets in Bit-representation as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces`. INPUT: - - ``facets_input`` -- tuple of facets, each facet a tuple of vertices, - vertices must be exactly ``range(nr_vertices)`` - - ``nr_vertices`` + - ``facets_input`` -- tuple of facets, each facet a tuple of Vrepr, + Vrepr must be exactly ``range(n_Vrepr)`` + - ``n_Vrepr`` OUTPUT: @@ -432,22 +432,22 @@ def facets_tuple_to_bit_repr_of_facets(tuple facets_input, size_t nr_vertices): ....: from sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces \ ....: cimport ListOfFaces ....: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: cimport bit_repr_to_vertex_list + ....: cimport bit_repr_to_Vrepr_list ....: from sage.rings.integer cimport smallInteger ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: from libc.stdint cimport uint64_t ....: - ....: def bit_repr_to_vertex_list_wrapper(list_of_faces, index): + ....: def bit_repr_to_Vrepr_list_wrapper(list_of_faces, index): ....: cdef MemoryAllocator mem = MemoryAllocator() ....: cdef size_t *output ....: cdef ListOfFaces faces = list_of_faces - ....: output = mem.allocarray(faces.nr_vertices, + ....: output = mem.allocarray(faces.n_atoms, ....: sizeof(size_t)) ....: cdef uint64_t * data = faces.data[index] - ....: length = bit_repr_to_vertex_list( + ....: length = bit_repr_to_Vrepr_list( ....: data, output, faces.face_length) ....: return tuple(smallInteger(output[i]) for i in range(length)) - ....: ''') + ....: ''') # long time sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ ....: import facets_tuple_to_bit_repr_of_facets @@ -455,7 +455,7 @@ def facets_tuple_to_bit_repr_of_facets(tuple facets_input, size_t nr_vertices): ....: (0,1,5), (1,2,5), (2,3,5), (3,0,5)) sage: facets = facets_tuple_to_bit_repr_of_facets(bi_pyr, 6) sage: for i in range(8): - ....: print(bit_repr_to_vertex_list_wrapper(facets, i)) + ....: print(bit_repr_to_Vrepr_list_wrapper(facets, i)) (0, 1, 4) (1, 2, 4) (2, 3, 4) @@ -466,27 +466,26 @@ def facets_tuple_to_bit_repr_of_facets(tuple facets_input, size_t nr_vertices): (0, 3, 5) """ cdef Py_ssize_t i - cdef ListOfFaces facets = ListOfFaces(len(facets_input), - nr_vertices) + cdef ListOfFaces facets = ListOfFaces(len(facets_input), n_Vrepr) cdef size_t face_length = facets.face_length cdef uint64_t **facets_data = facets.data for i in range(len(facets_input)): # filling each facet with the the data from the corresponding facet - vertex_list_to_bit_repr(facets_input[i], facets_data[i], face_length) + Vrepr_list_to_bit_repr(facets_input[i], facets_data[i], face_length) return facets -def facets_tuple_to_bit_repr_of_vertices(tuple facets_input, size_t nr_vertices): +def facets_tuple_to_bit_repr_of_Vrepr(tuple facets_input, size_t n_Vrepr): r""" - Initialize vertices in Bit-representation as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces`. + Initialize Vrepresentatives in Bit-representation as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces`. - Each vertex is represented as the facets it is contained in. + Each Vrepresentative is represented as the facets it is contained in. Those are the facets of the polar polyhedron, if it exists. INPUT: - - ``facets_input`` -- tuple of facets, each facet a tuple of vertices, - vertices must be exactly ``range(nr_vertices)`` - - ``nr_vertices`` + - ``facets_input`` -- tuple of facets, each facet a tuple of Vrepr, + Vrepr must be exactly ``range(n_Vrepr)`` + - ``n_Vrepr`` OUTPUT: @@ -499,30 +498,30 @@ def facets_tuple_to_bit_repr_of_vertices(tuple facets_input, size_t nr_vertices) ....: from sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces \ ....: cimport ListOfFaces ....: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: cimport bit_repr_to_vertex_list + ....: cimport bit_repr_to_Vrepr_list ....: from sage.rings.integer cimport smallInteger ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: from libc.stdint cimport uint64_t ....: - ....: def bit_repr_to_vertex_list_wrapper(list_of_faces, index): + ....: def bit_repr_to_Vrepr_list_wrapper(list_of_faces, index): ....: cdef MemoryAllocator mem = MemoryAllocator() ....: cdef size_t *output ....: cdef ListOfFaces faces = list_of_faces - ....: output = mem.allocarray(faces.nr_vertices, + ....: output = mem.allocarray(faces.n_atoms, ....: sizeof(size_t)) ....: cdef uint64_t * data = faces.data[index] - ....: length = bit_repr_to_vertex_list( + ....: length = bit_repr_to_Vrepr_list( ....: data, output, faces.face_length) ....: return tuple(smallInteger(output[i]) for i in range(length)) ....: ''') sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: import facets_tuple_to_bit_repr_of_vertices + ....: import facets_tuple_to_bit_repr_of_Vrepr sage: bi_pyr = ((0,1,4), (1,2,4), (2,3,4), (3,0,4), ....: (0,1,5), (1,2,5), (2,3,5), (3,0,5)) - sage: vertices = facets_tuple_to_bit_repr_of_vertices(bi_pyr, 6) + sage: vertices = facets_tuple_to_bit_repr_of_Vrepr(bi_pyr, 6) sage: for i in range(6): - ....: print(bit_repr_to_vertex_list_wrapper(vertices, i)) + ....: print(bit_repr_to_Vrepr_list_wrapper(vertices, i)) (0, 3, 4, 7) (0, 1, 4, 5) (1, 2, 5, 6) @@ -530,53 +529,53 @@ def facets_tuple_to_bit_repr_of_vertices(tuple facets_input, size_t nr_vertices) (0, 1, 2, 3) (4, 5, 6, 7) """ - cdef size_t nr_facets = len(facets_input) + cdef size_t n_facets = len(facets_input) # Vertices in facet-representation will be a ``ListOfFaces`` - # with number of vertices faces and - # number of facets "vertices"/atoms. - cdef ListOfFaces vertices = ListOfFaces(nr_vertices, nr_facets) - cdef uint64_t **vertices_data = vertices.data + # with number of Vrepr faces and + # number of facets "Vrepr"/atoms. + cdef ListOfFaces Vrepr = ListOfFaces(n_Vrepr, n_facets) + cdef uint64_t **Vrepr_data = Vrepr.data # Initializing the data of ListOfFaces. - cdef size_t face_length = vertices.face_length + cdef size_t face_length = Vrepr.face_length cdef size_t i - for i in range(nr_vertices): - memset(vertices_data[i], 0, face_length*8) + for i in range(n_Vrepr): + memset(Vrepr_data[i], 0, face_length*8) cdef size_t input_facet # will iterate over indices of facets_input cdef size_t position # determines the position in output of entry cdef size_t value # determines which bit will be set in output[position] - cdef size_t input_vertex # will iterate over vertices in facet ``input_facet`` + cdef size_t input_Vrepr # will iterate over vertices in facet ``input_facet`` - for input_facet in range(nr_facets): + for input_facet in range(n_facets): value = input_facet % 64 position = input_facet//64 - for input_vertex in facets_input[input_facet]: - # Iff the input-vertex is in the input-facet, - # then in facet-representation of the vertices - # input-facet is a vertex of intput-vertex. - vertices_data[input_vertex][position] += vertex_to_bit_dictionary(value) - return vertices - -cdef inline size_t bit_repr_to_vertex_list(uint64_t *face, size_t *output, + for input_Vrepr in facets_input[input_facet]: + # Iff the input-Vrepr is in the input-facet, + # then in facet-representation of the Vrepr + # input-facet is a Vrepr of intput-Vrepr. + Vrepr_data[input_Vrepr][position] += vertex_to_bit_dictionary(value) + return Vrepr + +cdef inline size_t bit_repr_to_Vrepr_list(uint64_t *face, size_t *output, size_t face_length) except -1: r""" - Convert a bitrep-representation to a list of vertices. Return length of representation. + Convert a bitrep-representation to a list of Vrepr. Return length of representation. - Basically this is an inverse to :meth:`vertex_list_to_bit_repr`. - Instead of returning a tuple, it stores the vertices in ``output``. + Basically this is an inverse to :meth:`Vrepr_list_to_bit_repr`. + Instead of returning a tuple, it stores the Vrepr in ``output``. INPUT: - ``face`` -- a Bit-representation of a face - - ``output`` -- an array of ``size_t`` long enough to contain all vertices + - ``output`` -- an array of ``size_t`` long enough to contain all Vrepr of that face (``face_length*64`` will suffice) - ``face_length`` -- the length of ``face`` OUTPUT: - - store vertices in ``output`` + - store Vrepr in ``output`` - return "length" of ``output`` EXAMPLES:: @@ -585,12 +584,12 @@ cdef inline size_t bit_repr_to_vertex_list(uint64_t *face, size_t *output, ....: from sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces \ ....: cimport ListOfFaces ....: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: cimport bit_repr_to_vertex_list, vertex_list_to_bit_repr + ....: cimport bit_repr_to_Vrepr_list, Vrepr_list_to_bit_repr ....: from sage.rings.integer cimport smallInteger ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: from libc.stdint cimport uint64_t ....: - ....: def bit_repr_to_vertex_list_wrapper(tup): + ....: def bit_repr_to_Vrepr_list_wrapper(tup): ....: cdef MemoryAllocator mem = MemoryAllocator() ....: cdef size_t *output ....: cdef length = len(tup) @@ -600,27 +599,27 @@ cdef inline size_t bit_repr_to_vertex_list(uint64_t *face, size_t *output, ....: data = mem.allocarray(length, 8) ....: for i in range(len(tup)): ....: data[i] = tup[i] - ....: outputlength = bit_repr_to_vertex_list( + ....: outputlength = bit_repr_to_Vrepr_list( ....: data, output, length) ....: return tuple(smallInteger(output[i]) for i in range(outputlength)) ....: ''') # long time - sage: bit_repr_to_vertex_list_wrapper((17, 31)) # long time + sage: bit_repr_to_Vrepr_list_wrapper((17, 31)) # long time (59, 63, 123, 124, 125, 126, 127) - sage: bit_repr_to_vertex_list_wrapper((13,)) # long time + sage: bit_repr_to_Vrepr_list_wrapper((13,)) # long time (60, 61, 63) - sage: bit_repr_to_vertex_list_wrapper((0, 61)) # long time + sage: bit_repr_to_Vrepr_list_wrapper((0, 61)) # long time (122, 123, 124, 125, 127) TESTS: - Testing that :meth`bit_repr_to_vertex_list` is the - inverse to :meth:`vertex_list_to_bit_repr`:: + Testing that :meth`bit_repr_to_Vrepr_list` is the + inverse to :meth:`Vrepr_list_to_bit_repr`:: sage: cython(''' ....: from libc.stdint cimport uint64_t ....: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: cimport bit_repr_to_vertex_list, vertex_list_to_bit_repr + ....: cimport bit_repr_to_Vrepr_list, Vrepr_list_to_bit_repr ....: from sage.misc.prandom import randint ....: ....: cdef uint64_t[2] face @@ -630,12 +629,12 @@ cdef inline size_t bit_repr_to_vertex_list(uint64_t *face, size_t *output, ....: for _ in range(10): ....: st = set(randint(0,127) for i in range(40)) ....: tup = tuple(sorted(tuple(st))) - ....: vertex_list_to_bit_repr(tup, face, 2) - ....: length = bit_repr_to_vertex_list(face, output, 2) + ....: Vrepr_list_to_bit_repr(tup, face, 2) + ....: length = bit_repr_to_Vrepr_list(face, output, 2) ....: tup2 = tuple(output[i] for i in range(length)) ....: if not tup == tup2: - ....: print('``bit_repr_to_vertex_list`` does not behave', - ....: 'as the inverse of ``vertex_list_to_bit_repr``') + ....: print('``bit_repr_to_Vrepr_list`` does not behave', + ....: 'as the inverse of ``Vrepr_list_to_bit_repr``') ....: ''') # long time """ cdef size_t i, j @@ -647,7 +646,7 @@ cdef inline size_t bit_repr_to_vertex_list(uint64_t *face, size_t *output, for j in range(64): if copy >= vertex_to_bit_dictionary(j): # Then face[i] has the j-th bit set to 1. - # This corresponds to face containing vertex i*64 + j. + # This corresponds to face containing Vrepr i*64 + j. output[output_length] = i*64 + j output_length += 1 copy -= vertex_to_bit_dictionary(j) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd index 1a89371e71c..398bb2a6b45 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd @@ -3,6 +3,7 @@ from libc.stdint cimport uint64_t from sage.ext.memory_allocator cimport MemoryAllocator from sage.structure.sage_object cimport SageObject from .list_of_faces cimport ListOfFaces +from .combinatorial_face cimport CombinatorialFace @cython.final cdef class FaceIterator(SageObject): @@ -12,9 +13,10 @@ cdef class FaceIterator(SageObject): cdef size_t *coatom_repr # a place where coatom-representaion of face will be stored cdef int current_dimension # dimension of current face, dual dimension if ``dual`` cdef int dimension # dimension of the polyhedron - cdef int nr_lines # ``_nr_lines`` of ``CombinatorialPolyhedron`` - cdef int output_dimension # only faces of this (dual?) dimension are considered - cdef int lowest_dimension # don't consider faces bewow this (dual?) dimension + cdef int n_lines # ``_n_lines`` of ``CombinatorialPolyhedron`` + cdef int output_dimension # only faces of this (dual?) dimension are considered + cdef int lowest_dimension # don't consider faces below this (dual?) dimension + cdef size_t _index # this counts the number of seen faces, useful for hasing the faces cdef MemoryAllocator _mem cdef tuple newfaces_lists # tuple to hold the ListOfFaces corresponding to maybe_newfaces cdef size_t face_length # stores length of the faces in terms of uint64_t @@ -35,7 +37,7 @@ cdef class FaceIterator(SageObject): # will ignore those changes when going up in dimension again. # This is why the number of faces in ``visited_all``depends on dimension. cdef uint64_t **visited_all - cdef size_t *nr_visited_all + cdef size_t *n_visited_all # ``maybe_newfaces`` is where all possible facets of a face are stored. # In dimension ``dim`` when visiting all faces of some face, @@ -45,21 +47,22 @@ cdef class FaceIterator(SageObject): # ``newfaces`` will point to those faces in ``maybe_newfaces`` # that are of codimension 1 and not already visited. cdef uint64_t ***newfaces - cdef size_t *nr_newfaces # number of newfaces for each dimension + cdef size_t *n_newfaces # number of newfaces for each dimension # After having visited a face completely, we want to add it to ``visited_all``. # ``first_dim[i]`` will indicate, wether there is one more face in - # ``newfaces[i]`` then ``nr_newfaces[i]`` suggests + # ``newfaces[i]`` then ``n_newfaces[i]`` suggests # that has to be added to ``visited_all``. # If ``first_time[i] == False``, we still need to - # add ``newfaces[i][nr_newfaces[i]]`` to ``visited_all``. + # add ``newfaces[i][n_newfaces[i]]`` to ``visited_all``. cdef bint *first_time # The number of elements in newfaces[current_dimension], # that have not been visited yet. cdef size_t yet_to_visit - cdef inline int next_face(self) except -1 + cdef inline CombinatorialFace next_face(self) + cdef inline int next_dimension(self) except -1 cdef inline int next_face_loop(self) except -1 cdef size_t length_atom_repr(self) except -1 cdef size_t set_coatom_repr(self) except -1 diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx index 981c95b84c9..ccb9ed02024 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx @@ -11,22 +11,23 @@ except for intervals including the empty face. Terminology in this module: -- Vertices -- ``[vertices, rays, lines]`` of the polyhedron. +- Vrepr -- ``[vertices, rays, lines]`` of the polyhedron. +- Hrepr -- inequalities and equalities of the polyhedron. - Facets -- facets of the polyhedron. - Coatoms -- the faces from which all others are constructed in - the face iterator. This will be facets or vertices. + the face iterator. This will be facets or Vrepr. In non-dual mode, faces are constructed as intersections of the facets. In dual mode, the are constructed theoretically as joins of vertices. The coatoms are reprsented as incidences with the atoms they contain. -- Atoms -- facets or vertices depending on application of algorithm. +- Atoms -- facets or Vrepr depending on application of algorithm. Atoms are reprsented as incidences of coatoms they are contained in. -- Vertex-Representation -- represents a face by a list of vertices it contains. -- Facet-Representation -- represents a face by a list of facets it is contained in. -- Bit-Representation -- represents incidences as ``uint64_t``-array, where +- Vrepresentation -- represents a face by a list of Vrepr it contains. +- Hrepresentation -- represents a face by a list of Hrepr it is contained in. +- bit representation -- represents incidences as ``uint64_t``-array, where each Bit represents one incidences. There might be trailing zeros, to fit alignment-requirements. In most instances, faces are represented by the @@ -47,55 +48,63 @@ Construct a face iterator:: sage: FaceIterator(C, False, output_dimension=2) Iterator over the 2-faces of a polyhedron of dimension 3 -Iterator in the non-dual mode starts with facets. -By default the dimension of the current face is given:: +Iterator in the non-dual mode starts with facets:: sage: it = FaceIterator(C, False) - sage: next(it) - 2 - -Iterator in the dual-mode start with vertices:: + sage: [next(it) for _ in range(9)] + [Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron] + +Iterator in the dual-mode starts with vertices:: sage: it = FaceIterator(C, True) - sage: next(it) - 0 + sage: [next(it) for _ in range(7)] + [Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron] -Obtain the vertex-representation:: +Obtain the Vrepresentation:: sage: it = FaceIterator(C, False) - sage: next(it) - 2 - sage: it.vertex_repr() + sage: face = next(it) + sage: face.Vrepr() (A vertex at (0, -1, 0), A vertex at (0, 0, -1), A vertex at (1, 0, 0)) - - sage: it.length_vertex_repr() + sage: face.length_Vrepr() 3 Obtain the facet-representation:: sage: it = FaceIterator(C, True) - sage: next(it) - 0 - sage: it.facet_repr() + sage: face = next(it) + sage: face.Hrepr() (An inequality (-1, -1, 1) x + 1 >= 0, An inequality (-1, -1, -1) x + 1 >= 0, An inequality (-1, 1, -1) x + 1 >= 0, An inequality (-1, 1, 1) x + 1 >= 0) - sage: it.facet_repr(names=False) + sage: face.Hrepr(names=False) (4, 5, 6, 7) - - sage: it.length_facet_repr() + sage: face.length_Hrepr() 4 In non-dual mode one can ignore all faces contained in the current face:: sage: it = FaceIterator(C, False) - sage: next(it) - 2 - sage: it.facet_repr(names=False) + sage: face = next(it) + sage: face.Hrepr(names=False) (7,) sage: it.ignore_subfaces() - sage: [it.facet_repr(names=False) for _ in it] + sage: [face.Hrepr(names=False) for face in it] [(6,), (5,), (4,), @@ -119,12 +128,11 @@ In non-dual mode one can ignore all faces contained in the current face:: In dual mode one can ignore all faces that contain the current face:: sage: it = FaceIterator(C, True) - sage: next(it) - 0 - sage: it.vertex_repr(names=False) + sage: face = next(it) + sage: face.Vrepr(names=False) (5,) sage: it.ignore_supfaces() - sage: [it.vertex_repr(names=False) for _ in it] + sage: [face.Vrepr(names=False) for face in it] [(4,), (3,), (2,), @@ -162,7 +170,7 @@ from __future__ import absolute_import, division, print_function from sage.rings.integer cimport smallInteger from cysignals.signals cimport sig_check, sig_on, sig_off -from .conversions cimport bit_repr_to_vertex_list +from .conversions cimport bit_repr_to_Vrepr_list from .base cimport CombinatorialPolyhedron from .bit_vector_operations cimport get_next_level, count_atoms, bit_repr_to_coatom_repr @@ -173,7 +181,7 @@ cdef class FaceIterator(SageObject): r""" A class to iterate over all faces of a polyhedron. - Constructs all proper from the facets. In dual mode, constructs all proper + Constructs all proper faces from the facets. In dual mode, constructs all proper faces from the vertices. Dual will be faster for less vertices than facets. INPUT: @@ -195,55 +203,42 @@ cdef class FaceIterator(SageObject): sage: P = polytopes.cuboctahedron() sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter() - - By default it will give the dimension of each face:: - - sage: [next(it) for _ in range(14)] - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] - - Get more knowledge about current face:: - - sage: it.length_vertex_repr() - 2 - sage: it.vertex_repr() - (A vertex at (1, 0, -1), A vertex at (1, 1, 0)) - sage: it.length_facet_repr() - 2 - sage: it.facet_repr() - (An inequality (-1, 0, 0) x + 1 >= 0, An inequality (-1, -1, 1) x + 2 >= 0) - sage: it.current_face_dimension() - 1 - - Ignore faces the current face contains:: - - sage: it.ignore_supfaces() - sage: [next(it) for _ in range(5)] - [1, 1, 2, 2, 1] - sage: it.length_facet_repr() - 2 + sage: next(it) + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron Construct faces by the dual or not:: sage: it = C.face_iter(dual=False) - sage: next(it) - 2 - sage: next(it) + sage: next(it).dimension() 2 - sage: it.ignore_subfaces() - sage: it.ignore_supfaces() - Traceback (most recent call last): - ... - ValueError: only possible when in dual mode + sage: it = C.face_iter(dual=True) - sage: next(it) - 0 - sage: next(it) + sage: next(it).dimension() 0 - sage: it.ignore_supfaces() - sage: it.ignore_subfaces() + + For unbounded polyhedra only non-dual iteration is possible:: + + sage: P = Polyhedron(rays=[[0,0,1], [0,1,0], [1,0,0]]) + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter() + sage: [face.Vrepr() for face in it] + [(A vertex at (0, 0, 0), + A ray in the direction (0, 1, 0), + A ray in the direction (1, 0, 0)), + (A vertex at (0, 0, 0), + A ray in the direction (0, 0, 1), + A ray in the direction (1, 0, 0)), + (A vertex at (0, 0, 0), + A ray in the direction (0, 0, 1), + A ray in the direction (0, 1, 0)), + (A vertex at (0, 0, 0), A ray in the direction (1, 0, 0)), + (A vertex at (0, 0, 0), A ray in the direction (0, 1, 0)), + (A vertex at (0, 0, 0),), + (A vertex at (0, 0, 0), A ray in the direction (0, 0, 1))] + sage: it = C.face_iter(dual=True) Traceback (most recent call last): ... - ValueError: only possible when not in dual mode + ValueError: cannot iterate over dual of unbounded Polyedron Construct a FaceIterator only yielding dimension `2` faces:: @@ -258,6 +253,84 @@ cdef class FaceIterator(SageObject): sage: C.f_vector() (1, 120, 240, 150, 30, 1) + In non-dual mode one can ignore all faces contained in the current face:: + + sage: P = polytopes.cube() + sage: C = CombinatorialPolyhedron(P) + sage: it = C.face_iter(dual=False) + sage: face = next(it) + sage: face.Hrepr(names=False) + (5,) + sage: it.ignore_subfaces() + sage: [face.Hrepr(names=False) for face in it] + [(4,), + (3,), + (2,), + (1,), + (0,), + (3, 4), + (2, 4), + (1, 4), + (1, 3, 4), + (1, 2, 4), + (1, 3), + (0, 3), + (0, 1, 3), + (1, 2), + (0, 2), + (0, 1, 2), + (0, 1)] + + sage: it = C.face_iter(dual=True) + sage: next(it) + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron + sage: it.ignore_subfaces() + Traceback (most recent call last): + ... + ValueError: only possible when not in dual mode + + In dual mode one can ignore all faces that contain the current face:: + + sage: it = C.face_iter(dual=True) + sage: next(it) + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron + sage: face = next(it) + sage: face.Vrepr(names=False) + (6,) + sage: [face.Vrepr(names=False) for face in it] + [(5,), + (4,), + (3,), + (2,), + (1,), + (0,), + (6, 7), + (5, 7), + (3, 7), + (4, 5, 6, 7), + (2, 3, 6, 7), + (1, 3, 5, 7), + (4, 6), + (2, 6), + (0, 2, 4, 6), + (4, 5), + (1, 5), + (0, 1, 4, 5), + (0, 4), + (2, 3), + (1, 3), + (0, 1, 2, 3), + (0, 2), + (0, 1)] + + sage: it = C.face_iter(dual=False) + sage: next(it) + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron + sage: it.ignore_supfaces() + Traceback (most recent call last): + ... + ValueError: only possible when in dual mode + ALGORITHM: The algorithm to visit all proper faces exactly once is roughly @@ -340,7 +413,7 @@ cdef class FaceIterator(SageObject): sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter() sage: f_vector = [1, 0, 0, 0, 1] - sage: for d in it: f_vector[d+1] += 1 + sage: for face in it: f_vector[face.dimension()+1] += 1 sage: print ('f_vector of permutahedron(4): ', f_vector) f_vector of permutahedron(4): [1, 24, 36, 14, 1] @@ -355,14 +428,14 @@ cdef class FaceIterator(SageObject): self.face = NULL self.dimension = C.dimension() self.current_dimension = self.dimension -1 - self.nr_lines = C._nr_lines + self.n_lines = C._n_lines self._mem = MemoryAllocator() # We will not yield the empty face. # If there are `n` lines, than there # are no faces below dimension `n`. # The dimension of the level-sets in the face lattice jumps from `n` to `-1`. - self.lowest_dimension = self.nr_lines + self.lowest_dimension = self.n_lines if output_dimension is not None: if not output_dimension in range(0,self.dimension): @@ -372,36 +445,36 @@ cdef class FaceIterator(SageObject): self.output_dimension = self.dimension - 1 - output_dimension else: self.output_dimension = output_dimension - self.lowest_dimension = max(self.nr_lines, self.output_dimension) + self.lowest_dimension = max(self.n_lines, self.output_dimension) else: self.output_dimension = -2 if dual: self.atoms = C.bitrep_facets - self.coatoms = C.bitrep_vertices + self.coatoms = C.bitrep_Vrepr else: self.coatoms = C.bitrep_facets - self.atoms = C.bitrep_vertices + self.atoms = C.bitrep_Vrepr self.face_length = self.coatoms.face_length self._V = C._V self._H = C._H self._equalities = C._equalities - self.atom_repr = self._mem.allocarray(self.coatoms.nr_vertices, sizeof(size_t)) - self.coatom_repr = self._mem.allocarray(self.coatoms.nr_faces, sizeof(size_t)) + self.atom_repr = self._mem.allocarray(self.coatoms.n_atoms, sizeof(size_t)) + self.coatom_repr = self._mem.allocarray(self.coatoms.n_faces, sizeof(size_t)) - if self.dimension == 0 or self.coatoms.nr_faces == 0: + if self.dimension == 0 or self.coatoms.n_faces == 0: # As we will only yield proper faces, # there is nothing to yield in those cases. # We have to discontinue initialization, - # as it assumes ``self.dimension > 0`` and ``self.nr_faces > 0``. + # as it assumes ``self.dimension > 0`` and ``self.n_faces > 0``. self.current_dimension = self.dimension return - # We may assume ``dimension > 0`` and ``nr_faces > 0``. + # We may assume ``dimension > 0`` and ``n_faces > 0``. # Initialize ``maybe_newfaces``, # the place where the new faces are being stored. - self.newfaces_lists = tuple(ListOfFaces(self.coatoms.nr_faces, self.coatoms.nr_vertices) + self.newfaces_lists = tuple(ListOfFaces(self.coatoms.n_faces, self.coatoms.n_atoms) for i in range(self.dimension -1)) self.maybe_newfaces = self._mem.allocarray((self.dimension -1), sizeof(uint64_t **)) for i in range(self.dimension -1): @@ -409,26 +482,27 @@ cdef class FaceIterator(SageObject): self.maybe_newfaces[i] = some_list.data # Initialize ``visited_all``. - self.visited_all = self._mem.allocarray(self.coatoms.nr_faces, sizeof(uint64_t *)) - self.nr_visited_all = self._mem.allocarray(self.dimension, sizeof(size_t)) - self.nr_visited_all[self.dimension -1] = 0 + self.visited_all = self._mem.allocarray(self.coatoms.n_faces, sizeof(uint64_t *)) + self.n_visited_all = self._mem.allocarray(self.dimension, sizeof(size_t)) + self.n_visited_all[self.dimension -1] = 0 # Initialize ``newfaces``, which will point to the new faces of codimension 1, # which have not been visited yet. self.newfaces = self._mem.allocarray(self.dimension, sizeof(uint64_t **)) for i in range(self.dimension - 1): - self.newfaces[i] = self._mem.allocarray(self.coatoms.nr_faces, sizeof(uint64_t *)) + self.newfaces[i] = self._mem.allocarray(self.coatoms.n_faces, sizeof(uint64_t *)) self.newfaces[self.dimension - 1] = self.coatoms.data # we start with coatoms - # Initialize ``nr_newfaces``. - self.nr_newfaces = self._mem.allocarray(self.dimension, sizeof(size_t)) - self.nr_newfaces[self.dimension - 1] = self.coatoms.nr_faces + # Initialize ``n_newfaces``. + self.n_newfaces = self._mem.allocarray(self.dimension, sizeof(size_t)) + self.n_newfaces[self.dimension - 1] = self.coatoms.n_faces # Initialize ``first_time``. self.first_time = self._mem.allocarray(self.dimension, sizeof(bint)) self.first_time[self.dimension - 1] = True - self.yet_to_visit = self.coatoms.nr_faces + self.yet_to_visit = self.coatoms.n_faces + self._index = 0 def _repr_(self): r""" @@ -455,22 +529,26 @@ cdef class FaceIterator(SageObject): def __next__(self): r""" - Visit the next face and return its dimension. + Return the next face. EXAMPLES:: sage: P = polytopes.cube() sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter() sage: [next(it) for _ in range(7)] - [2, 2, 2, 2, 2, 2, 1] + [Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron] """ - cdef int d = self.next_face() - if unlikely(d == self.dimension): + cdef CombinatorialFace face = self.next_face() + if unlikely(self.current_dimension == self.dimension): raise StopIteration - # If ``dual == 0`` return current dimension, - # if ``dual == 1`` translate current dimension to dual and then return. - return smallInteger(self.dual*(self.dimension-1-d) + (1-self.dual)*d) + return face next = __next__ @@ -482,7 +560,20 @@ cdef class FaceIterator(SageObject): sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter() sage: [d for d in it] - [2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1] + [Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 2-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 0-dimensional face of a 3-dimensional polyhedron, + Combinatorial type of a 1-dimensional face of a 3-dimensional polyhedron] """ return self @@ -502,255 +593,6 @@ cdef class FaceIterator(SageObject): """ raise NotImplementedError - def current_face_dimension(self): - r""" - Return the dimension of the current face. - - EXAMPLES:: - - sage: P = polytopes.associahedron(['A', 3]) - sage: C = CombinatorialPolyhedron(P) - sage: it = C.face_iter() - sage: next(it) - 2 - sage: it.current_face_dimension() - 2 - sage: all(d == it.current_face_dimension() for d in it) - True - """ - if unlikely(self.face is NULL): - raise ValueError("iterator not set to a face yet") - if unlikely(self.current_dimension == self.dimension): - raise ValueError("iterator consumed") - # If ``dual == 0`` return current dimension, - # if ``dual == 1`` translate current dimension to dual and then return. - return smallInteger(self.dual*(self.dimension-1-self.current_dimension) + - (1-self.dual)*self.current_dimension) - - def vertex_repr(self, names=True): - r""" - Return the vertex-representation of the current face. - - The vertex-representation consists of - the ``[vertices, rays, lines]`` that face contains. - - INPUT: - - - ``names`` -- if ``True`` returns the names of the ``[vertices, rays, lines]`` - as given on initialization of the :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.base.CombinatorialPolyhedron` - - EXAMPLES:: - - sage: P = polytopes.permutahedron(5) - sage: C = CombinatorialPolyhedron(P) - sage: it = C.face_iter(dimension=2) - sage: next(it) - 2 - sage: it.vertex_repr() - (A vertex at (4, 1, 5, 2, 3), - A vertex at (4, 2, 5, 1, 3), - A vertex at (5, 1, 4, 2, 3), - A vertex at (5, 2, 4, 1, 3)) - sage: next(it) - 2 - sage: it.vertex_repr() - (A vertex at (4, 1, 5, 2, 3), - A vertex at (4, 1, 5, 3, 2), - A vertex at (5, 1, 4, 2, 3), - A vertex at (5, 1, 4, 3, 2)) - sage: next(it) - 2 - sage: it.vertex_repr(False) - (76, 77, 82, 83, 88, 89) - sage: next(it) - 2 - sage: it.vertex_repr(False) - (77, 83, 101, 107) - - sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3],[0,2,3],[1,2,3]]) - sage: it = C.face_iter() - sage: for i in it: (i, it.vertex_repr()) - (2, (1, 2, 3)) - (2, (0, 2, 3)) - (2, (0, 1, 3)) - (2, (0, 1, 2)) - (1, (2, 3)) - (1, (1, 3)) - (1, (1, 2)) - (0, (3,)) - (0, (2,)) - (0, (1,)) - (1, (0, 3)) - (1, (0, 2)) - (0, (0,)) - (1, (0, 1)) - """ - cdef size_t length - if unlikely(self.face is NULL): - raise ValueError("iterator not set to a face yet") - if self.dual: - # if dual, the vertex-represention corresponds to the coatom-representation - length = self.set_coatom_repr() - if names and self._V: - return tuple(self._V[self.coatom_repr[i]] - for i in range(length)) - else: - return tuple(smallInteger(self.coatom_repr[i]) - for i in range(length)) - else: - # if not dual, the vertex-represention corresponds to the atom-representation - length = self.set_atom_repr() - if names and self._V: - return tuple(self._V[self.atom_repr[i]] - for i in range(length)) - else: - return tuple(smallInteger(self.atom_repr[i]) - for i in range(length)) - - def length_vertex_repr(self): - r""" - Return the length of the :class:`vertex_repr`. - - Might be faster than `len(self.vertex_repr())`. - - EXAMPLES:: - - sage: P = polytopes.cube() - sage: C = CombinatorialPolyhedron(P) - sage: it = C.face_iter() - sage: all(it.length_vertex_repr() == len(it.vertex_repr()) for _ in it) - True - """ - if unlikely(self.face is NULL): - raise ValueError("iterator not set to a face yet") - if self.dual: - return smallInteger(self.set_coatom_repr()) - else: - return smallInteger(self.length_atom_repr()) - - def facet_repr(self, names=True): - r""" - Return the facet-representation of the current face. - - The facet-representation consists of the facets - that contain the face and of the equalities of the polyhedron. - - INPUT: - - - ``names`` -- if ``True`` returns the names of the ``[facets, equations]`` - as given on initialization of :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.base.CombinatorialPolyhedron` - - EXAMPLES:: - - sage: P = polytopes.permutahedron(5) - sage: C = CombinatorialPolyhedron(P) - sage: it = C.face_iter(2) - sage: next(it) - 2 - sage: it.facet_repr() - (An inequality (0, 1, 0, 1, 0) x - 3 >= 0, - An inequality (0, 1, 0, 1, 1) x - 6 >= 0, - An equation (1, 1, 1, 1, 1) x - 15 == 0) - sage: next(it) - 2 - sage: it.facet_repr() - (An inequality (0, 1, 0, 0, 0) x - 1 >= 0, - An inequality (0, 1, 0, 1, 1) x - 6 >= 0, - An equation (1, 1, 1, 1, 1) x - 15 == 0) - sage: next(it) - 2 - sage: it.facet_repr(False) - (12, 29) - sage: next(it) - 2 - sage: it.facet_repr(False) - (6, 29) - - sage: P = polytopes.cyclic_polytope(4,6) - sage: C = CombinatorialPolyhedron(P) - sage: it = C.face_iter() - sage: next(it) - 0 - sage: it.facet_repr() - (An inequality (-20, 29, -10, 1) x + 0 >= 0, - An inequality (60, -47, 12, -1) x + 0 >= 0, - An inequality (30, -31, 10, -1) x + 0 >= 0, - An inequality (10, -17, 8, -1) x + 0 >= 0, - An inequality (-154, 71, -14, 1) x + 120 >= 0, - An inequality (-78, 49, -12, 1) x + 40 >= 0) - sage: next(it) - 0 - sage: it.facet_repr() - (An inequality (-50, 35, -10, 1) x + 24 >= 0, - An inequality (-12, 19, -8, 1) x + 0 >= 0, - An inequality (-20, 29, -10, 1) x + 0 >= 0, - An inequality (60, -47, 12, -1) x + 0 >= 0, - An inequality (-154, 71, -14, 1) x + 120 >= 0, - An inequality (-78, 49, -12, 1) x + 40 >= 0) - sage: next(it) - 0 - sage: it.facet_repr(False) - (0, 1, 2, 4, 5, 7) - sage: next(it) - 0 - sage: it.facet_repr(False) - (0, 1, 5, 6, 7, 8) - sage: next(it) - 0 - sage: it.facet_repr(False) - (0, 1, 2, 3, 6, 8) - sage: [next(it) for _ in range(3)] - [0, 1, 1] - sage: it.facet_repr(False) - (4, 5, 7) - sage: it.facet_repr() - (An inequality (60, -47, 12, -1) x + 0 >= 0, - An inequality (30, -31, 10, -1) x + 0 >= 0, - An inequality (-154, 71, -14, 1) x + 120 >= 0) - """ - cdef size_t length - if unlikely(self.face is NULL): - raise ValueError("iterator not set to a face yet") - if not self.dual: - # if not dual, the facet-represention corresponds to the coatom-representation - length = self.set_coatom_repr() # fill self.coatom_repr_face - if names and self._H: - return tuple(self._H[self.coatom_repr[i]] - for i in range(length)) + self._equalities - else: - return tuple(smallInteger(self.coatom_repr[i]) - for i in range(length)) - else: - # if dual, the facet-represention corresponds to the atom-representation - length = self.set_atom_repr() # fill self.atom_repr_face - if names and self._H: - return tuple(self._H[self.atom_repr[i]] - for i in range(length)) + self._equalities - else: - return tuple(smallInteger(self.atom_repr[i]) - for i in range(length)) - - def length_facet_repr(self): - r""" - Returns the length of the :meth:`facet_repr`. - - Might be faster than ``len(self.facet_repr())``. - - EXAMPLES:: - - sage: P = polytopes.cube() - sage: C = CombinatorialPolyhedron(P) - sage: it = C.face_iter() - sage: all(it.length_facet_repr() == len(it.facet_repr()) for _ in it) - True - """ - if unlikely(self.face is NULL): - raise ValueError("iterator not set to a face yet") - if not self.dual: - return smallInteger(self.set_coatom_repr()) - else: - return smallInteger(self.length_atom_repr()) - def ignore_subfaces(self): r""" :class:`FaceIterator` will not visit any faces of the current face. @@ -762,14 +604,14 @@ cdef class FaceIterator(SageObject): sage: P = polytopes.Gosset_3_21() sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter(dual=False) - sage: nr_non_simplex_faces = 1 - sage: for d in it: - ....: if it.length_vertex_repr() > d + 1: - ....: nr_non_simplex_faces += 1 + sage: n_non_simplex_faces = 1 + sage: for face in it: + ....: if face.length_Vrepr() > face.dimension() + 1: + ....: n_non_simplex_faces += 1 ....: else: ....: it.ignore_subfaces() ....: - sage: nr_non_simplex_faces + sage: n_non_simplex_faces 127 """ if unlikely(self.dual): @@ -781,8 +623,8 @@ cdef class FaceIterator(SageObject): # This will make the iterator skip those faces. # Also, this face will not be added a second time to ``visited_all``, # as there are no new faces. - self.visited_all[self.nr_visited_all[self.current_dimension]] = self.face - self.nr_visited_all[self.current_dimension] += 1 + self.visited_all[self.n_visited_all[self.current_dimension]] = self.face + self.n_visited_all[self.current_dimension] += 1 def ignore_supfaces(self): r""" @@ -795,14 +637,14 @@ cdef class FaceIterator(SageObject): sage: P = polytopes.Gosset_3_21() sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter(dual=True) - sage: nr_faces_with_non_simplex_quotient = 1 - sage: for d in it: - ....: if it.length_facet_repr() > C.dimension() - d + 1: - ....: nr_faces_with_non_simplex_quotient += 1 + sage: n_faces_with_non_simplex_quotient = 1 + sage: for face in it: + ....: if face.length_Hrepr() > C.dimension() - face.dimension() + 1: + ....: n_faces_with_non_simplex_quotient += 1 ....: else: ....: it.ignore_supfaces() ....: - sage: nr_faces_with_non_simplex_quotient + sage: n_faces_with_non_simplex_quotient 4845 """ if unlikely(not self.dual): @@ -814,10 +656,20 @@ cdef class FaceIterator(SageObject): # This will make the iterator skip those faces. # Also, this face will not be added a second time to ``visited_all``, # as there are no new faces. - self.visited_all[self.nr_visited_all[self.current_dimension]] = self.face - self.nr_visited_all[self.current_dimension] += 1 + self.visited_all[self.n_visited_all[self.current_dimension]] = self.face + self.n_visited_all[self.current_dimension] += 1 + + cdef inline CombinatorialFace next_face(self): + r""" + Set attribute ``face`` to the next face and return it as + :class:`sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face.CombinatorialFace`. + """ + self.next_dimension() + if unlikely(self.current_dimension == self.dimension): + return None + return CombinatorialFace(self) - cdef inline int next_face(self) except -1: + cdef inline int next_dimension(self) except -1: r""" Set attribute ``face`` to the next face and return the dimension. @@ -839,6 +691,7 @@ cdef class FaceIterator(SageObject): cdef int dim = self.dimension while (not self.next_face_loop()) and (self.current_dimension < dim): sig_check() + self._index += 1 return self.current_dimension cdef inline int next_face_loop(self) except -1: @@ -854,10 +707,10 @@ cdef class FaceIterator(SageObject): # just prevent it from crashing. raise StopIteration - # Getting ``[faces, nr_faces, nr_visited_all]`` according to dimension. + # Getting ``[faces, n_faces, n_visited_all]`` according to dimension. cdef uint64_t **faces = self.newfaces[self.current_dimension] - cdef size_t nr_faces = self.nr_newfaces[self.current_dimension] - cdef size_t nr_visited_all = self.nr_visited_all[self.current_dimension] + cdef size_t n_faces = self.n_newfaces[self.current_dimension] + cdef size_t n_visited_all = self.n_visited_all[self.current_dimension] if (self.output_dimension > -2) and (self.output_dimension != self.current_dimension): # If only a specific dimension was requested (i.e. ``self.output_dimension > -2``), @@ -876,55 +729,55 @@ cdef class FaceIterator(SageObject): self.current_dimension += 1 return 0 - if nr_faces <= 1: + if n_faces <= 1: # There will be no more faces from intersections. self.current_dimension += 1 return 0 # We will visit the last face now. - self.nr_newfaces[self.current_dimension] -= 1 - nr_faces -= 1 + self.n_newfaces[self.current_dimension] -= 1 + n_faces -= 1 if not self.first_time[self.current_dimension]: - # In this case there exists ``faces[nr_faces + 1]``, of which we + # In this case there exists ``faces[n_faces + 1]``, of which we # have visited all faces, but which was not added to # ``visited_all`` yet. - self.visited_all[nr_visited_all] = faces[nr_faces + 1] - self.nr_visited_all[self.current_dimension] += 1 - nr_visited_all = self.nr_visited_all[self.current_dimension] + self.visited_all[n_visited_all] = faces[n_faces + 1] + self.n_visited_all[self.current_dimension] += 1 + n_visited_all = self.n_visited_all[self.current_dimension] else: - # Once we have visited all faces of ``faces[nr_faces]``, we want + # Once we have visited all faces of ``faces[n_faces]``, we want # to add it to ``visited_all``. self.first_time[self.current_dimension] = False - # Get the faces of codimension 1 contained in ``faces[nr_faces]``, + # Get the faces of codimension 1 contained in ``faces[n_faces]``, # which we have not yet visited. cdef size_t newfacescounter sig_on() newfacescounter = get_next_level( - faces, nr_faces + 1, self.maybe_newfaces[self.current_dimension-1], + faces, n_faces + 1, self.maybe_newfaces[self.current_dimension-1], self.newfaces[self.current_dimension-1], - self.visited_all, nr_visited_all, self.face_length) + self.visited_all, n_visited_all, self.face_length) sig_off() if newfacescounter: - # ``faces[nr_faces]`` contains new faces. + # ``faces[n_faces]`` contains new faces. # We will visted them on next call, starting with codimension 1. # Setting the variables correclty for next call of ``next_face_loop``. self.current_dimension -= 1 self.first_time[self.current_dimension] = True - self.nr_newfaces[self.current_dimension] = newfacescounter - self.nr_visited_all[self.current_dimension] = nr_visited_all + self.n_newfaces[self.current_dimension] = newfacescounter + self.n_visited_all[self.current_dimension] = n_visited_all self.yet_to_visit = newfacescounter return 0 else: - # ``faces[nr_faces]`` contains no new faces. + # ``faces[n_faces]`` contains no new faces. # Hence there is no need to add it to ``visited_all``. # NOTE: # For the methods ``ignore_subfaces`` and ``ignore_supfaces`` - # this step needs to be done, as ``faces[nr_faces]`` might + # this step needs to be done, as ``faces[n_faces]`` might # have been added manually to ``visited_all``. # So this step is required to respect boundaries of ``visited_all``. self.first_time[self.current_dimension] = True @@ -934,6 +787,8 @@ cdef class FaceIterator(SageObject): r""" Compute the number of atoms in the current face by counting the number of set bits. + + This is a shortcut of :class:`sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face.CombinatorialFace.length_atom_repr` """ if self.face: return count_atoms(self.face, self.face_length) @@ -945,17 +800,21 @@ cdef class FaceIterator(SageObject): r""" Set ``coatom_repr`` to be the coatom-representation of the current face. Return its length. + + This is a shortcut of :class:`sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face.CombinatorialFace.set_coatom_repr` """ - cdef size_t nr_coatoms = self.coatoms.nr_faces + cdef size_t n_coatoms = self.coatoms.n_faces cdef uint64_t **coatoms = self.coatoms.data cdef size_t face_length = self.face_length - return bit_repr_to_coatom_repr(self.face, coatoms, nr_coatoms, + return bit_repr_to_coatom_repr(self.face, coatoms, n_coatoms, face_length, self.coatom_repr) cdef size_t set_atom_repr(self) except -1: r""" Set ``atom_repr`` to be the atom-representation of the current face. Return its length. + + This is a shortcut of :class:`sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face.CombinatorialFace.set_atom_repr` """ cdef size_t face_length = self.face_length - return bit_repr_to_vertex_list(self.face, self.atom_repr, face_length) + return bit_repr_to_Vrepr_list(self.face, self.atom_repr, face_length) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_all_faces.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_all_faces.pxd index ab585f20bd7..14d0005e300 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_all_faces.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_all_faces.pxd @@ -2,6 +2,7 @@ cimport cython from libc.stdint cimport uint64_t from sage.ext.memory_allocator cimport MemoryAllocator from .list_of_faces cimport ListOfFaces +from .combinatorial_face cimport CombinatorialFace @cython.final cdef class ListOfAllFaces: @@ -15,8 +16,8 @@ cdef class ListOfAllFaces: cdef size_t *atom_repr # a place where atom-representaion of face will be stored cdef size_t *coatom_repr # a place where coatom-representaion of face will be stored - # Atoms and coatoms are the vertices/facets of the Polyedron. - # If ``dual == 0``, then coatoms are facets, atoms vertices and vice versa. + # Atoms and coatoms are the Vrepr/facets of the Polyedron. + # If ``dual == 0``, then coatoms are facets, atoms Vrepresentatives and vice versa. cdef ListOfFaces atoms, coatoms # All faces are stored in ``faces``. ``faces[i]`` stores all faces of @@ -40,14 +41,15 @@ cdef class ListOfAllFaces: cdef int _add_face(self, int face_dim, uint64_t *face) except -1 cdef int _sort(self) except -1 - cdef int _sort_one_list(self, uint64_t **faces, size_t nr_faces) except -1 + cdef int _sort_one_list(self, uint64_t **faces, size_t n_faces) except -1 cdef int _sort_one_list_loop( self, uint64_t **inp, uint64_t **output1, - uint64_t **output2, size_t nr_faces) except -1 + uint64_t **output2, size_t n_faces) except -1 cdef inline size_t find_face(self, int dimension, uint64_t *face) except -1 cdef inline bint is_smaller(self, uint64_t *one, uint64_t *two) cdef inline int is_equal(self, int dimension, size_t index, uint64_t *face) except -1 + cdef CombinatorialFace get_face(self, int dimension, size_t index) cdef size_t set_coatom_repr(self, int dimension, size_t index) except -1 cdef size_t set_atom_repr(self, int dimension, size_t index) except -1 cdef void incidence_init(self, int dimension_one, int dimension_two) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_all_faces.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_all_faces.pyx index fce876d4a8e..2a37e46d72d 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_all_faces.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_all_faces.pyx @@ -8,22 +8,23 @@ the face lattice of a polyhedron. Terminology in this module: -- Vertices -- ``[vertices, rays, lines]`` of the polyhedron. +- Vrepr -- ``[vertices, rays, lines]`` of the polyhedron. +- Hrepr -- inequalities and equalities of the polyhedron. - Facets -- facets of the polyhedron. - Coatoms -- the faces from which all others are constructed in - the face iterator. This will be facets or vertices. + the face iterator. This will be facets or Vrepr. In non-dual mode, faces are constructed as intersections of the facets. In dual mode, the are constructed theoretically as joins of vertices. The coatoms are reprsented as incidences with the atoms they contain. -- Atoms -- facets or vertices depending on application of algorithm. +- Atoms -- facets or Vrepr depending on application of algorithm. Atoms are reprsented as incidences of coatoms they are contained in. -- Vertex-Representation -- represents a face by a list of vertices it contains. -- Facet-Representation -- represents a face by a list of facets it is contained in. -- Bit-Representation -- represents incidences as ``uint64_t``-array, where +- Vrepresentation -- represents a face by a list of VRepr it contains. +- Hrepresentation -- represents a face by a list of Hrepr it is contained in. +- bit representation -- represents incidences as ``uint64_t``-array, where each Bit represents one incidences. There might be trailing zeros, to fit alignment-requirements. In most instances, faces are represented by the @@ -61,11 +62,11 @@ AUTHOR: from __future__ import absolute_import, division, print_function from .conversions \ import facets_tuple_to_bit_repr_of_facets, \ - facets_tuple_to_bit_repr_of_vertices + facets_tuple_to_bit_repr_of_Vrepr from sage.rings.integer cimport smallInteger from libc.string cimport memcmp, memcpy, memset -from .conversions cimport vertex_list_to_bit_repr, bit_repr_to_vertex_list +from .conversions cimport Vrepr_list_to_bit_repr, bit_repr_to_Vrepr_list from .base cimport CombinatorialPolyhedron from .face_iterator cimport FaceIterator from .bit_vector_operations cimport intersection, bit_repr_to_coatom_repr @@ -128,7 +129,7 @@ cdef class ListOfAllFaces: self._mem = MemoryAllocator() self.dimension = C.dimension() self.dual = False - if C.bitrep_facets.nr_faces > C.bitrep_vertices.nr_faces: + if C.bitrep_facets.n_faces > C.bitrep_Vrepr.n_faces: self.dual = True if C._unbounded: self.dual = False @@ -160,24 +161,24 @@ cdef class ListOfAllFaces: if self.dimension == 0: # In case of the 0-dimensional polyhedron, we have to fix atoms and coatoms. # So far this didn't matter, as we only iterated over proper faces. - self.atoms = facets_tuple_to_bit_repr_of_vertices(((),), 1) + self.atoms = facets_tuple_to_bit_repr_of_Vrepr(((),), 1) self.coatoms = facets_tuple_to_bit_repr_of_facets(((),), 1) self.face_length = self.coatoms.face_length else: self.atoms = face_iter.atoms self.coatoms = face_iter.coatoms - cdef size_t nr_atoms = self.atoms.nr_faces - self.atom_repr = self._mem.allocarray(self.coatoms.nr_vertices, sizeof(size_t)) - self.coatom_repr = self._mem.allocarray(self.coatoms.nr_faces, sizeof(size_t)) + cdef size_t n_atoms = self.atoms.n_faces + self.atom_repr = self._mem.allocarray(self.coatoms.n_atoms, sizeof(size_t)) + self.coatom_repr = self._mem.allocarray(self.coatoms.n_faces, sizeof(size_t)) # Initialize the data for ``faces``: cdef ListOfFaces coatoms_mem - self.faces_mem = tuple(ListOfFaces(self.f_vector[i+1], nr_atoms) + self.faces_mem = tuple(ListOfFaces(self.f_vector[i+1], n_atoms) for i in range(-1, self.dimension-1)) if self.dimension > -1: # the coatoms self.faces_mem += (self.coatoms,) - self.faces_mem += (ListOfFaces(1, nr_atoms),) # the full polyhedron + self.faces_mem += (ListOfFaces(1, n_atoms),) # the full polyhedron # Setting up a pointer to raw data of ``faces``: self.faces = self._mem.allocarray(self.dimension + 2, sizeof(uint64_t **)) @@ -189,15 +190,15 @@ cdef class ListOfAllFaces: if self.dimension != 0: # Initialize the empty face. # In case ``dimension == 0``, we would overwrite the coatoms. - vertex_list_to_bit_repr((), self.faces[0][0], self.face_length) + Vrepr_list_to_bit_repr((), self.faces[0][0], self.face_length) # Intialize the full polyhedron - vertex_list_to_bit_repr(tuple(j for j in range(nr_atoms)), + Vrepr_list_to_bit_repr(tuple(j for j in range(n_atoms)), self.faces[self.dimension + 1][0], self.face_length) # Attributes for iterating over the incidences. self.is_incidence_initialized = 0 - cdef ListOfFaces incidence_face_mem = ListOfFaces(1, nr_atoms) + cdef ListOfFaces incidence_face_mem = ListOfFaces(1, n_atoms) self.incidence_face = incidence_face_mem.data[0] self.faces_mem += (incidence_face_mem,) # needs to be stored somewhere @@ -205,13 +206,13 @@ cdef class ListOfAllFaces: cdef int d if face_iter.current_dimension != self.dimension: # If there are proper faces. - d = face_iter.next_face() + d = face_iter.next_dimension() while (d == self.dimension - 1): # We already have the coatoms. - d = face_iter.next_face() + d = face_iter.next_dimension() while (d < self.dimension): self._add_face(d, face_iter.face) - d = face_iter.next_face() + d = face_iter.next_dimension() # Sorting the faces, except for coatoms. self._sort() @@ -247,23 +248,23 @@ cdef class ListOfAllFaces: # Sort each level set, except for coatoms, full- and empty polyhedron. self._sort_one_list(self.faces[i], self.f_vector[i]) - cdef int _sort_one_list(self, uint64_t **faces, size_t nr_faces) except -1: + cdef int _sort_one_list(self, uint64_t **faces, size_t n_faces) except -1: r""" - Sort ``faces`` of length ``nr_faces``. + Sort ``faces`` of length ``n_faces``. See :meth:`sort`. """ cdef MemoryAllocator mem = MemoryAllocator() # Merge sort needs a second list of pointers. - cdef uint64_t **extra_mem = mem.allocarray(nr_faces, sizeof(uint64_t *)) + cdef uint64_t **extra_mem = mem.allocarray(n_faces, sizeof(uint64_t *)) # Sort the faces using merge sort. - self._sort_one_list_loop(faces, faces, extra_mem, nr_faces) + self._sort_one_list_loop(faces, faces, extra_mem, n_faces) cdef int _sort_one_list_loop( self, uint64_t **inp, uint64_t **output1, - uint64_t **output2, size_t nr_faces) except -1: + uint64_t **output2, size_t n_faces) except -1: r""" This is merge sort. @@ -275,18 +276,18 @@ cdef class ListOfAllFaces: See :meth:`sort`. """ - if unlikely(nr_faces == 0): + if unlikely(n_faces == 0): # Prevent it from crashing. # In this case there is nothing to do anyway. return 0 - if nr_faces == 1: + if n_faces == 1: # The final case, where there is only one element. output1[0] = inp[0] return 0 - cdef size_t middle = nr_faces//2 - cdef size_t len_upper_half = nr_faces - middle + cdef size_t middle = n_faces//2 + cdef size_t len_upper_half = n_faces - middle # Sort the upper and lower half of ``inp`` iteratively into ``output2``. self._sort_one_list_loop(inp, output2, output1, middle) @@ -297,7 +298,7 @@ cdef class ListOfAllFaces: cdef size_t i = 0 # index through lower half cdef size_t j = middle # index through upper half cdef size_t counter = 0 # counts how many elements have been "merged" already - while i < middle and j < nr_faces: + while i < middle and j < n_faces: # Compare the lowest elements of lower and upper half. if self.is_smaller(output2[i], output2[j]): output1[counter] = output2[i] @@ -315,7 +316,7 @@ cdef class ListOfAllFaces: counter += 1 else: # Add the remaining elements of upper half. - while j < nr_faces: + while j < n_faces: output1[counter] = output2[j] j += 1 counter += 1 @@ -348,8 +349,7 @@ cdef class ListOfAllFaces: sage: P = polytopes.permutahedron(4) sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter() - sage: next(it) - 2 + sage: face = next(it) sage: find_face_from_iterator(it, C) Traceback (most recent call last): ... @@ -367,22 +367,22 @@ cdef class ListOfAllFaces: raise IndexError("dimension out of range") cdef size_t start = 0 cdef size_t middle - cdef nr_faces = self.f_vector[dimension + 1] + cdef n_faces = self.f_vector[dimension + 1] cdef uint64_t **faces = self.faces[dimension + 1] - while (nr_faces > 1): + while (n_faces > 1): # In each iteration step, we will look for ``face`` in - # ``faces[start:start+nr_faces]``. - middle = nr_faces//2 + # ``faces[start:start+n_faces]``. + middle = n_faces//2 if self.is_smaller(face, faces[middle + start]): # If face is in the list, then in the lower half. # Look for face in ``faces[start : start + middle]`` in next step. - nr_faces = middle + n_faces = middle else: # If face is in the list, then in the upper half. - # Look for face in ``faces[start+middle:start+nr_faces]``, i.e. - # ``faces[start + middle : (start + middle) + nr_faces - middle]``. - nr_faces -= middle + # Look for face in ``faces[start+middle:start+n_faces]``, i.e. + # ``faces[start + middle : (start + middle) + n_faces - middle]``. + n_faces -= middle start += middle return start @@ -405,13 +405,9 @@ cdef class ListOfAllFaces: cdef size_t i return (0 == memcmp(face, face2, self.face_length*8)) - def vertex_repr(self, dimension, index, names=True): + cdef CombinatorialFace get_face(self, int dimension, size_t index): r""" - Return the vertex-representation of the face of dimension ``dimension`` - and index ``index``. - - The vertex-representation consists of - the ``[vertices, rays, lines]`` that face contains. + Return the face of dimension ``dimension`` and index ``index``. INPUT: @@ -427,7 +423,7 @@ cdef class ListOfAllFaces: ....: from sage.geometry.polyhedron.combinatorial_polyhedron.base \ ....: cimport CombinatorialPolyhedron, FaceIterator, ListOfAllFaces ....: - ....: def vertex_repr_via_all_faces_from_iterator(it, C1, names): + ....: def face_via_all_faces_from_iterator(it, C1): ....: cdef FaceIterator face_iter = it ....: cdef CombinatorialPolyhedron C = C1 ....: cdef int dimension = face_iter.current_dimension @@ -436,163 +432,38 @@ cdef class ListOfAllFaces: ....: if not (all_faces.dual == it.dual): ....: raise ValueError("iterator and allfaces not in same mode") ....: index = all_faces.find_face(dimension, face_iter.face) - ....: return all_faces.vertex_repr(dimension, index, names) + ....: return all_faces.get_face(dimension, index) ....: ''') sage: P = polytopes.permutahedron(4) sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter(dimension=1) - sage: next(it) - 1 - sage: vertex_repr_via_all_faces_from_iterator(it, C, True) + sage: face = next(it) + sage: face_via_all_faces_from_iterator(it, C).Vrepr() (A vertex at (3, 1, 4, 2), A vertex at (3, 2, 4, 1)) - sage: it.vertex_repr() + sage: face.Vrepr() (A vertex at (3, 1, 4, 2), A vertex at (3, 2, 4, 1)) - sage: all(vertex_repr_via_all_faces_from_iterator(it, C, True) == - ....: it.vertex_repr() for _ in it) + sage: all(face_via_all_faces_from_iterator(it, C).Vrepr() == + ....: face.Vrepr() for face in it) True sage: P = polytopes.twenty_four_cell() sage: C = CombinatorialPolyhedron(P) sage: it = C.face_iter() - sage: d = next(it) - sage: while (d == 3): d = next(it) - sage: vertex_repr_via_all_faces_from_iterator(it, C, True) + sage: face = next(it) + sage: while (face.dimension() == 3): face = next(it) + sage: face_via_all_faces_from_iterator(it, C).Vrepr() (A vertex at (-1/2, 1/2, -1/2, -1/2), A vertex at (-1/2, 1/2, 1/2, -1/2), A vertex at (0, 0, 0, -1)) - sage: vertex_repr_via_all_faces_from_iterator(it, C, False) - (5, 7, 11) - sage: all(vertex_repr_via_all_faces_from_iterator(it, C, False) == - ....: it.vertex_repr(False) for _ in it) + sage: all(face_via_all_faces_from_iterator(it, C).Vrepr(False) == + ....: face.Vrepr(False) for face in it) True """ cdef size_t length if self.dual: - # if dual, the vertex-represention corresponds to the coatom-representation - dimension = self.dimension - 1 - dimension # if dual, the dimensions are reversed - length = self.set_coatom_repr(dimension, index) - if names and self._V: - return tuple(self._V[self.coatom_repr[i]] - for i in range(length)) - else: - return tuple(smallInteger(self.coatom_repr[i]) - for i in range(length)) - else: - # if not dual, the vertex-represention corresponds to the atom-representation - length = self.set_atom_repr(dimension, index) - if names and self._V: - return tuple(self._V[self.atom_repr[i]] - for i in range(length)) - else: - return tuple(smallInteger(self.atom_repr[i]) - for i in range(length)) - - def facet_repr(self, dimension, index, names=True): - r""" - Return the facet-representation of the face of dimension ``dimension`` - and index ``index``. - - The facet-representation consists of the facets - that contain the face and of the equalities of the polyhedron. - - INPUT: - - - ``dimension`` -- dimension of the face - - ``index`` -- index of the face - - ``names`` -- if ``True`` returns the names of the ``[facets, equations]`` - as given on initialization of :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.base.CombinatorialPolyhedron` - - EXAMPLES:: - - sage: cython(''' - ....: from libc.stdint cimport uint64_t - ....: from sage.geometry.polyhedron.combinatorial_polyhedron.base \ - ....: cimport CombinatorialPolyhedron, FaceIterator, ListOfAllFaces - ....: - ....: def facet_repr_via_all_faces_from_iterator(it, C1, names): - ....: cdef FaceIterator face_iter = it - ....: cdef CombinatorialPolyhedron C = C1 - ....: cdef int dimension = face_iter.current_dimension - ....: C._record_all_faces() - ....: cdef ListOfAllFaces all_faces = C._all_faces - ....: if not (all_faces.dual == it.dual): - ....: raise ValueError("iterator and allfaces not in same mode") - ....: index = all_faces.find_face(dimension, face_iter.face) - ....: return all_faces.facet_repr(dimension, index, names) - ....: ''') - sage: P = polytopes.permutahedron(4) - sage: C = CombinatorialPolyhedron(P) - sage: it = C.face_iter(dimension=1) - sage: next(it) - 1 - sage: facet_repr_via_all_faces_from_iterator(it, C, True) - (An inequality (0, 0, -1, 0) x + 4 >= 0, - An inequality (0, 1, 0, 1) x - 3 >= 0, - An equation (1, 1, 1, 1) x - 10 == 0) - sage: all(facet_repr_via_all_faces_from_iterator(it, C, True) == - ....: it.facet_repr() for _ in it) - True - - sage: P = polytopes.twenty_four_cell() - sage: C = CombinatorialPolyhedron(P) - sage: it = C.face_iter() - sage: d = next(it) - sage: while (d == 3): d = next(it) - sage: facet_repr_via_all_faces_from_iterator(it, C, True) - (An inequality (1, 0, 0, 1) x + 1 >= 0, An inequality (0, -1, 0, 1) x + 1 >= 0) - sage: facet_repr_via_all_faces_from_iterator(it, C, False) - (16, 23) - sage: all(facet_repr_via_all_faces_from_iterator(it, C, False) == - ....: it.facet_repr(False) for _ in it) - True - - sage: P = Polyhedron(vertices=[[0,1]]) - sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice_facet_repr(0) - (An equation (0, 1) x - 1 == 0, An equation (1, 0) x + 0 == 0) - sage: C.face_lattice_facet_repr(1) - (An equation (0, 1) x - 1 == 0, An equation (1, 0) x + 0 == 0) - sage: C.face_lattice_vertex_repr(0) - () - sage: C.face_lattice_vertex_repr(1) - (A vertex at (0, 1),) - - sage: P = Polyhedron() - sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice_facet_repr(0) - (An equation -1 == 0,) - - sage: P = Polyhedron(lines=[[0,1]]) - sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice_facet_repr(0) - (An equation (1, 0) x + 0 == 0,) - sage: C.face_lattice_facet_repr(1) - (An equation (1, 0) x + 0 == 0,) - """ - cdef size_t length - if not self.dual: - # if not dual, the vertex-represention corresponds to the coatom-representation - length = self.set_coatom_repr(dimension, index) - if unlikely((self.coatoms.nr_faces == 0 or self.dimension == 0) - and names and self._H is not None): - # in this case the facet does not correspond to a Hrep - return self._equalities + self._H - elif names and self._H: - return tuple(self._H[self.coatom_repr[i]] - for i in range(length)) + self._equalities - else: - return tuple(smallInteger(self.coatom_repr[i]) - for i in range(length)) - else: - # if dual, the facet-represention corresponds to the atom-representation + # if dual, the Vrepresention corresponds to the coatom-representation dimension = self.dimension - 1 - dimension # if dual, the dimensions are reversed - length = self.set_atom_repr(dimension, index) - if names and self._H: - return tuple(self._H[self.atom_repr[i]] - for i in range(length)) + self._equalities - else: - return tuple(smallInteger(self.atom_repr[i]) - for i in range(length)) + return CombinatorialFace(self, dimension=dimension, index=index) cdef size_t set_coatom_repr(self, int dimension, size_t index) except -1: r""" @@ -608,14 +479,14 @@ cdef class ListOfAllFaces: raise ValueError("no face of dimension %s"%dimension) if unlikely(index >= self.f_vector[dimension + 1]): raise IndexError("no %s-th face of dimension %s"%(index, dimension)) - if unlikely(self.coatoms.nr_faces == 0): + if unlikely(self.coatoms.n_faces == 0): return 0 - cdef size_t nr_coatoms = self.f_vector[self.dimension] + cdef size_t n_coatoms = self.f_vector[self.dimension] cdef uint64_t **coatoms = self.faces[self.dimension] cdef size_t face_length = self.face_length cdef uint64_t *face = self.faces[dimension+1][index] - return bit_repr_to_coatom_repr(face, coatoms, nr_coatoms, + return bit_repr_to_coatom_repr(face, coatoms, n_coatoms, face_length, self.coatom_repr) cdef size_t set_atom_repr(self, int dimension, size_t index) except -1: @@ -635,7 +506,7 @@ cdef class ListOfAllFaces: cdef size_t face_length = self.face_length cdef uint64_t *face = self.faces[dimension+1][index] - return bit_repr_to_vertex_list(face, self.atom_repr, face_length) + return bit_repr_to_Vrepr_list(face, self.atom_repr, face_length) cdef void incidence_init(self, int dimension_one, int dimension_two): r""" @@ -701,7 +572,7 @@ cdef class ListOfAllFaces: ``two[0]`` will represent the index of a face in ``dimension_two`` according to their order in :class:`ListOfAllFaces`. - Use :meth:`vertex_repr` and :meth:`facet_repr` to interpret the output. + Use :meth:`Vrepr` and :meth:`Hrepr` to interpret the output. ALGORITHM: diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd index 037f48eb78c..57884c29791 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd @@ -7,12 +7,12 @@ cdef class ListOfFaces: cdef MemoryAllocator _mem # ``face_length`` is the length of each face in terms of ``uint64_t``. - cdef readonly size_t nr_faces, face_length, nr_vertices + cdef readonly size_t n_faces, face_length, n_atoms # ``data`` points to the raw data. - # It will be of "type" ``uint64_t[nr_faces][face_length]`` + # It will be of "type" ``uint64_t[n_faces][face_length]`` cdef uint64_t **data cpdef int compute_dimension(self) except -2 - cdef int compute_dimension_loop(self, uint64_t **faces, size_t nr_faces, + cdef int compute_dimension_loop(self, uint64_t **faces, size_t n_faces, size_t face_length) except -2 diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx index c1474d9845c..ee28c94e3c9 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx @@ -31,12 +31,12 @@ Obtain the facets of a polyhedron:: sage: face_list.compute_dimension() 3 -Obtain the vertices of a polyhedron as facet-incidences:: +Obtain the Vrepresentation of a polyhedron as facet-incidences:: sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: import incidence_matrix_to_bit_repr_of_vertices + ....: import incidence_matrix_to_bit_repr_of_Vrepr sage: P = polytopes.associahedron(['A',3]) - sage: face_list = incidence_matrix_to_bit_repr_of_vertices(P.incidence_matrix()) + sage: face_list = incidence_matrix_to_bit_repr_of_Vrepr(P.incidence_matrix()) sage: face_list.compute_dimension() 3 @@ -47,12 +47,12 @@ Obtain the facets of a polyhedron as :class:`ListOfFaces` from a facet list:: sage: facets = ((0,1,2), (0,1,3), (0,2,3), (1,2,3)) sage: face_list = facets_tuple_to_bit_repr_of_facets(facets, 4) -Likewise for the vertices as facet-incidences:: +Likewise for the Vrepresenatives as facet-incidences:: sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ - ....: import facets_tuple_to_bit_repr_of_vertices + ....: import facets_tuple_to_bit_repr_of_Vrepr sage: facets = ((0,1,2), (0,1,3), (0,2,3), (1,2,3)) - sage: face_list = facets_tuple_to_bit_repr_of_vertices(facets, 4) + sage: face_list = facets_tuple_to_bit_repr_of_Vrepr(facets, 4) .. SEEALSO:: @@ -93,15 +93,15 @@ cdef class ListOfFaces: INPUT: - - ``nr_faces`` -- the number of faces to be stored - - ``nr_vertices`` -- the total number of vertices of the polyhedron + - ``n_faces`` -- the number of faces to be stored + - ``n_atoms`` -- the total number of atoms the faces contain .. SEEALSO:: :meth:`incidence_matrix_to_bit_repr_of_facets`, - :meth:`incidence_matrix_to_bit_repr_of_vertices`, + :meth:`incidence_matrix_to_bit_repr_of_Vrepr`, :meth:`facets_tuple_to_bit_repr_of_facets`, - :meth:`facets_tuple_to_bit_repr_of_vertices`, + :meth:`facets_tuple_to_bit_repr_of_Vrepr`, :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator.FaceIterator`, :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.base.CombinatorialPolyhedron`. @@ -112,12 +112,12 @@ cdef class ListOfFaces: sage: facets = ListOfFaces(5, 13) sage: facets.face_length in (1, 2, 4) True - sage: facets.nr_vertices + sage: facets.n_atoms 13 - sage: facets.nr_faces + sage: facets.n_faces 5 """ - def __init__(self, size_t nr_faces, size_t nr_vertices): + def __init__(self, size_t n_faces, size_t n_atoms): r""" Initialize :class:`ListOfFaces`. @@ -146,21 +146,21 @@ cdef class ListOfFaces: sage: TestSuite(sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces).run() """ - self.nr_faces = nr_faces - self.nr_vertices = nr_vertices + self.n_faces = n_faces + self.n_atoms = n_atoms self._mem = MemoryAllocator() # ``data`` will point to the faces as ``*uint64_t``. - self.data = self._mem.allocarray(nr_faces, sizeof(uint64_t *)) + self.data = self._mem.allocarray(n_faces, sizeof(uint64_t *)) # ``face_length`` is the length in terms of ``uint64_t`` # NOTE: This needs to be divisible by 2, if chunksize is 128 # and divisible by 4, if chunksize is 256. - self.face_length = ((nr_vertices - 1)//chunksize + 1)*chunksize//64 + self.face_length = ((n_atoms - 1)//chunksize + 1)*chunksize//64 cdef size_t i - for i in range(nr_faces): + for i in range(n_faces): # Allocate the memory for the i-th face. # We must allocate the memory for ListOfFaces overaligned: # - must be 16-byte aligned if chunksize = 128 @@ -180,14 +180,14 @@ cdef class ListOfFaces: ....: import ListOfFaces sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ ....: import facets_tuple_to_bit_repr_of_facets, \ - ....: facets_tuple_to_bit_repr_of_vertices + ....: facets_tuple_to_bit_repr_of_Vrepr sage: bi_pyr = ((0,1,4), (1,2,4), (2,3,4), (3,0,4), ....: (0,1,5), (1,2,5), (2,3,5), (3,0,5)) sage: facets = facets_tuple_to_bit_repr_of_facets(bi_pyr, 6) - sage: vertices = facets_tuple_to_bit_repr_of_vertices(bi_pyr, 6) + sage: Vrepr = facets_tuple_to_bit_repr_of_Vrepr(bi_pyr, 6) sage: facets.compute_dimension() 3 - sage: vertices.compute_dimension() + sage: Vrepr.compute_dimension() 3 ALGORITHM: @@ -214,7 +214,7 @@ cdef class ListOfFaces: ....: import ListOfFaces sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ ....: import incidence_matrix_to_bit_repr_of_facets, \ - ....: incidence_matrix_to_bit_repr_of_vertices + ....: incidence_matrix_to_bit_repr_of_Vrepr sage: bi_pyr = ((0,1,4), (1,2,4), (2,3,4), (3,0,4), ....: (0,1,5), (1,2,5), (2,3,5), (3,0,5)) sage: for _ in range(10): @@ -222,7 +222,7 @@ cdef class ListOfFaces: ....: for _ in range(randint(3,15))) ....: P = Polyhedron(vertices=points) ....: facets = incidence_matrix_to_bit_repr_of_facets(P.incidence_matrix()) - ....: vertices = incidence_matrix_to_bit_repr_of_vertices(P.incidence_matrix()) + ....: vertices = incidence_matrix_to_bit_repr_of_Vrepr(P.incidence_matrix()) ....: d1 = P.dimension() ....: if d1 == 0: ....: continue @@ -231,11 +231,11 @@ cdef class ListOfFaces: ....: if not d1 == d2 == d3: ....: print('calculation_dimension() seems to be incorrect') """ - if self.nr_faces == 0: + if self.n_faces == 0: raise TypeError("at least one face needed") - return self.compute_dimension_loop(self.data, self.nr_faces, self.face_length) + return self.compute_dimension_loop(self.data, self.n_faces, self.face_length) - cdef int compute_dimension_loop(self, uint64_t **faces, size_t nr_faces, + cdef int compute_dimension_loop(self, uint64_t **faces, size_t n_faces, size_t face_length) except -2: r""" Compute the dimension of a polyhedron by its facets. @@ -243,7 +243,7 @@ cdef class ListOfFaces: INPUT: - ``faces`` -- facets in Bit-representation - - ``nr_faces`` -- length of facesdata + - ``n_faces`` -- length of facesdata - ``face_length`` -- the length of each face in terms of ``uint64_t`` OUTPUT: @@ -254,34 +254,34 @@ cdef class ListOfFaces: :meth:`compute_dimension` """ - if nr_faces == 0: + if n_faces == 0: raise TypeError("wrong usage of ``compute_dimension_loop``,\n" + "at least one face needed.") - if nr_faces == 1: + if n_faces == 1: # We expect the face to be the empty polyhedron. # Possibly it contains more than one vertex/rays/lines. # The dimension of a polyhedron with this face as only facet is # the number of atoms it contains. return count_atoms(faces[0], face_length) - # ``maybe_newfaces`` are all intersection of ``faces[nr_faces -1]`` with previous faces. + # ``maybe_newfaces`` are all intersection of ``faces[n_faces -1]`` with previous faces. # It needs to be allcoated to store those faces. - cdef ListOfFaces maybe_newfaces_mem = ListOfFaces(nr_faces, face_length*64) + cdef ListOfFaces maybe_newfaces_mem = ListOfFaces(n_faces, face_length*64) cdef uint64_t **maybe_newfaces = maybe_newfaces_mem.data - # ``newfaces`` point to the actual facets of ``faces[nr_faces -1]``. + # ``newfaces`` point to the actual facets of ``faces[n_faces -1]``. cdef MemoryAllocator newfaces_mem = MemoryAllocator() - cdef uint64_t **newfaces = newfaces_mem.allocarray(nr_faces, sizeof(uint64_t *)) + cdef uint64_t **newfaces = newfaces_mem.allocarray(n_faces, sizeof(uint64_t *)) # Calculating ``maybe_newfaces`` and ``newfaces`` - # such that ``newfaces`` points to all facets of ``faces[nr_faces -1]``. - cdef size_t new_nr_faces + # such that ``newfaces`` points to all facets of ``faces[n_faces -1]``. + cdef size_t new_n_faces sig_on() - new_nr_faces = get_next_level(faces, nr_faces, maybe_newfaces, + new_n_faces = get_next_level(faces, n_faces, maybe_newfaces, newfaces, NULL, 0, face_length) sig_off() # compute the dimension of the polyhedron, # by calculating dimension of one of its faces. - return self.compute_dimension_loop(newfaces, new_nr_faces, face_length) + 1 + return self.compute_dimension_loop(newfaces, new_n_faces, face_length) + 1