diff --git a/src/doc/en/thematic_tutorials/geometry/polyhedra_quickref.rst b/src/doc/en/thematic_tutorials/geometry/polyhedra_quickref.rst index 96c43ffd6f5..fafc74d0074 100644 --- a/src/doc/en/thematic_tutorials/geometry/polyhedra_quickref.rst +++ b/src/doc/en/thematic_tutorials/geometry/polyhedra_quickref.rst @@ -122,6 +122,7 @@ List of Polyhedron methods :widths: 30, 70 :delim: | + :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.combinatorial_polyhedron` | the combinatorial polyhedron :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.face_lattice` | the face lattice :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.combinatorial_automorphism_group` | the automorphism group of the underlying combinatorial polytope :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.graph`, :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.vertex_graph` | underlying graph diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index fa0693ae9ab..63235af09e4 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -2731,6 +2731,27 @@ def is_compact(self): """ return self.n_rays() == 0 and self.n_lines() == 0 + @cached_method + def combinatorial_polyhedron(self): + r""" + Return the combinatorial type of ``self``. + + See :class:`sage.geometry.polyhedron.combinatorial_polyhedron.base.CombinatorialPolyhedron`. + + EXAMPLES:: + + sage: polytopes.cube().combinatorial_polyhedron() + A 3-dimensional combinatorial polyhedron with 6 facets + + sage: polytopes.cyclic_polytope(4,10).combinatorial_polyhedron() + A 4-dimensional combinatorial polyhedron with 35 facets + + sage: Polyhedron(rays=[[0,1], [1,0]]).combinatorial_polyhedron() + A 2-dimensional combinatorial polyhedron with 2 facets + """ + from sage.geometry.polyhedron.combinatorial_polyhedron.base import CombinatorialPolyhedron + return CombinatorialPolyhedron(self) + def is_simple(self): """ Test for simplicity of a polytope. @@ -5325,7 +5346,7 @@ def f_vector(self): sage: p.f_vector() (1, 7, 12, 7, 1) """ - return vector(ZZ, [len(x) for x in self.face_lattice().level_sets()]) + return self.combinatorial_polyhedron().f_vector() def vertex_graph(self): """ diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index 665029e7db3..a2cfe998c00 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -184,7 +184,7 @@ cdef class CombinatorialPolyhedron(SageObject): an integer:: sage: CombinatorialPolyhedron(-1).f_vector() - (1,) + (1) sage: CombinatorialPolyhedron(0).f_vector() (1, 1) sage: CombinatorialPolyhedron(5).f_vector() @@ -206,7 +206,9 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C A 2-dimensional combinatorial polyhedron with 2 facets sage: C.f_vector() - (1, 1, 2, 1) + Traceback (most recent call last): + ... + ValueError: not all vertices are intersections of facets sage: C.vertices() (A line in the direction (0, 1), A vertex at (1, 0), A vertex at (-1, 0)) @@ -252,15 +254,6 @@ cdef class CombinatorialPolyhedron(SageObject): (A vertex at (0, 0),) sage: data = P.incidence_matrix() sage: vert = P.Vrepresentation() - sage: C = CombinatorialPolyhedron(data, Vrepr=vert) - sage: C - A 2-dimensional combinatorial polyhedron with 2 facets - sage: C.f_vector() - (1, 1, 2, 1) - sage: C.vertices() - (A vertex at (0, 0), - A ray in the direction (0, 1), - A ray in the direction (1, 0)) sage: far_face = [i for i in range(3) if not P.Vrepresentation()[i].is_vertex()] sage: C = CombinatorialPolyhedron(data, Vrepr=vert, unbounded=True, far_face=far_face) sage: C @@ -272,7 +265,19 @@ cdef class CombinatorialPolyhedron(SageObject): sage: CombinatorialPolyhedron(3r) A 3-dimensional combinatorial polyhedron with 0 facets + Check that on wrong input subsequent calls of ``f_vector`` fail:: + sage: data = P.incidence_matrix() + sage: vert = P.Vrepresentation() + sage: C = CombinatorialPolyhedron(data, Vrepr=vert) + sage: C.f_vector() + Traceback (most recent call last): + ... + ValueError: not all vertices are intersections of facets + sage: C.f_vector() + Traceback (most recent call last): + ... + ValueError: not all vertices are intersections of facets """ def __init__(self, data, Vrepr=None, facets=None, unbounded=False, far_face=None): r""" @@ -759,7 +764,7 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C = CombinatorialPolyhedron(-1) sage: C.f_vector() - (1,) + (1) sage: C.n_facets() 0 @@ -1117,12 +1122,19 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C = CombinatorialPolyhedron(P) sage: C.f_vector() (1, 10, 45, 120, 185, 150, 50, 1) + + TESTS:: + + sage: type(C.f_vector()) + """ if not self._f_vector: self._compute_f_vector() if not self._f_vector: raise ValueError("could not determine f_vector") - return self._f_vector + from sage.modules.free_module_element import vector + from sage.rings.all import ZZ + return vector(ZZ, self._f_vector) def face_iter(self, dimension=None, dual=None): r""" @@ -1526,11 +1538,21 @@ cdef class CombinatorialPolyhedron(SageObject): # Copy ``f_vector``. if dual: + if dim > 1 and f_vector[1] < self.n_facets(): + # The input seemed to be wrong. + raise ValueError("not all facets are joins of vertices") + # We have computed the ``f_vector`` of the dual. # Reverse it: self._f_vector = \ tuple(smallInteger(f_vector[dim+1-i]) for i in range(dim+2)) + else: + if not self.unbounded() and dim > 1 \ + and f_vector[1] < self.length_Vrepr() - len(self.far_face_tuple()): + # The input seemed to be wrong. + raise ValueError("not all vertices are intersections of facets") + self._f_vector = tuple(smallInteger(f_vector[i]) for i in range(dim+2)) cdef int _compute_edges(self, dual) except -1: diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py index f108c81fe88..969e6f9e978 100644 --- a/src/sage/geometry/polyhedron/library.py +++ b/src/sage/geometry/polyhedron/library.py @@ -1314,7 +1314,7 @@ def truncated_dodecahedron(self, exact=True, base_ring=None, backend=None): sage: td.f_vector() Traceback (most recent call last): ... - KeyError: ... + ValueError: not all vertices are intersections of facets sage: td.base_ring() Real Double Field