# Base class for polyhedra: Methods for constructing new polyhedra#

Except for affine hull and affine hull projection.

class sage.geometry.polyhedron.base5.Polyhedron_base5(parent, Vrep, Hrep, Vrep_minimal=None, Hrep_minimal=None, pref_rep=None, mutable=False, **kwds)#

Methods constructing new polyhedra except for affine hull and affine hull projection.

bipyramid()#

Return a polyhedron that is a bipyramid over the original.

EXAMPLES:

sage: octahedron = polytopes.cross_polytope(3)
sage: cross_poly_4d = octahedron.bipyramid()
sage: cross_poly_4d.n_vertices()
8
sage: q = [list(v) for v in cross_poly_4d.vertex_generator()]
sage: q
[[-1, 0, 0, 0],
[0, -1, 0, 0],
[0, 0, -1, 0],
[0, 0, 0, -1],
[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0],
[1, 0, 0, 0]]


Now check that bipyramids of cross-polytopes are cross-polytopes:

sage: q2 = [list(v) for v in polytopes.cross_polytope(4).vertex_generator()]
sage: [v in q2 for v in q]
[True, True, True, True, True, True, True, True]

cartesian_product(other)#

Return the Cartesian product.

INPUT:

OUTPUT:

The Cartesian product of self and other with a suitable base ring to encompass the two.

EXAMPLES:

sage: P1 = Polyhedron([[0],[1]], base_ring=ZZ)
sage: P2 = Polyhedron([[0],[1]], base_ring=QQ)
sage: P1.product(P2)
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices


The Cartesian product is the product in the semiring of polyhedra:

sage: P1 * P1
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices
sage: P1 * P2
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
sage: P2 * P2
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
sage: 2 * P1
A 1-dimensional polyhedron in ZZ^1 defined as the convex hull of 2 vertices
sage: P1 * 2.0
A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices


An alias is cartesian_product():

sage: P1.cartesian_product(P2) == P1.product(P2)
True

convex_hull(other)#

Return the convex hull of the set-theoretic union of the two polyhedra.

INPUT:

OUTPUT:

The convex hull.

EXAMPLES:

sage: a_simplex = polytopes.simplex(3, project=True)
sage: verts = a_simplex.vertices()
sage: verts = [[x[0]*3/5+x[1]*4/5, -x[0]*4/5+x[1]*3/5, x[2]] for x in verts]
sage: another_simplex = Polyhedron(vertices = verts)
sage: simplex_union = a_simplex.convex_hull(another_simplex)
sage: simplex_union.n_vertices()
7

dilation(scalar)#

Return the dilated (uniformly stretched) polyhedron.

INPUT:

• scalar – A scalar, not necessarily in base_ring()

OUTPUT:

The polyhedron dilated by that scalar, possibly coerced to a bigger base ring.

EXAMPLES:

sage: p = Polyhedron(vertices = [[t,t^2,t^3] for t in srange(2,6)])
sage: next(p.vertex_generator())
A vertex at (2, 4, 8)
sage: p2 = p.dilation(2)
sage: next(p2.vertex_generator())
A vertex at (4, 8, 16)
sage: p.dilation(2) == p * 2
True

direct_sum(other)#

Return the direct sum of self and other.

The direct sum of two polyhedron is the subdirect sum of the two, when they have the origin in their interior. To avoid checking if the origin is contained in both, we place the affine subspace containing other at the center of self.

INPUT:

EXAMPLES:

sage: P1 = Polyhedron([[1],[2]], base_ring=ZZ)
sage: P2 = Polyhedron([[3],[4]], base_ring=QQ)
sage: ds = P1.direct_sum(P2);ds
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
sage: ds.vertices()
(A vertex at (1, 0),
A vertex at (2, 0),
A vertex at (3/2, -1/2),
A vertex at (3/2, 1/2))

face_split(face)#

Return the face splitting of the face face.

Splitting a face correspond to the bipyramid (see bipyramid()) of self where the two new vertices are placed above and below the center of face instead of the center of the whole polyhedron. The two new vertices are placed in the new dimension at height $$-1$$ and $$1$$.

INPUT:

• face – a PolyhedronFace or a Vertex

EXAMPLES:

sage: pentagon  = polytopes.regular_polygon(5)                      # optional - sage.rings.number_field
sage: f = pentagon.faces(1)[0]                                      # optional - sage.rings.number_field
sage: fsplit_pentagon = pentagon.face_split(f)                      # optional - sage.rings.number_field
sage: fsplit_pentagon.f_vector()                                    # optional - sage.rings.number_field
(1, 7, 14, 9, 1)

face_truncation(face, linear_coefficients=None, cut_frac=None)#

Return a new polyhedron formed by truncating a face by an hyperplane.

By default, the normal vector of the hyperplane used to truncate the polyhedron is obtained by taking the barycenter vector of the cone corresponding to the truncated face in the normal fan of the polyhedron. It is possible to change the direction using the option linear_coefficients.

To determine how deep the truncation is done, the method uses the parameter cut_frac. By default it is equal to $$\frac{1}{3}$$. Once the normal vector of the cutting hyperplane is chosen, the vertices of polyhedron are evaluated according to the corresponding linear function. The parameter $$\frac{1}{3}$$ means that the cutting hyperplane is placed $$\frac{1}{3}$$ of the way from the vertices of the truncated face to the next evaluated vertex.

INPUT:

• face – a PolyhedronFace

• linear_coefficients – tuple of integer. Specifies the coefficient of the normal vector of the cutting hyperplane used to truncate the face. The default direction is determined using the normal fan of the polyhedron.

• cut_frac – number between 0 and 1. Determines where the hyperplane cuts the polyhedron. A value close to 0 cuts very close to the face, whereas a value close to 1 cuts very close to the next vertex (according to the normal vector of the cutting hyperplane). Default is $$\frac{1}{3}$$.

OUTPUT:

A Polyhedron object, truncated as described above.

EXAMPLES:

sage: Cube = polytopes.hypercube(3)
sage: vertex_trunc1 = Cube.face_truncation(Cube.faces(0)[0])
sage: vertex_trunc1.f_vector()
(1, 10, 15, 7, 1)
sage: tuple(f.ambient_V_indices() for f in vertex_trunc1.faces(2))
((4, 5, 6, 7, 9),
(0, 3, 4, 8, 9),
(0, 1, 6, 7, 8),
(7, 8, 9),
(2, 3, 4, 5),
(1, 2, 5, 6),
(0, 1, 2, 3))
sage: vertex_trunc1.vertices()
(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/3, -1),
A vertex at (-1/3, -1, -1),
A vertex at (-1, -1, -1/3))
sage: vertex_trunc2 = Cube.face_truncation(Cube.faces(0)[0],cut_frac=1/2)
sage: vertex_trunc2.f_vector()
(1, 10, 15, 7, 1)
sage: tuple(f.ambient_V_indices() for f in vertex_trunc2.faces(2))
((4, 5, 6, 7, 9),
(0, 3, 4, 8, 9),
(0, 1, 6, 7, 8),
(7, 8, 9),
(2, 3, 4, 5),
(1, 2, 5, 6),
(0, 1, 2, 3))
sage: vertex_trunc2.vertices()
(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, 0, -1),
A vertex at (0, -1, -1),
A vertex at (-1, -1, 0))
sage: vertex_trunc3 = Cube.face_truncation(Cube.faces(0)[0],cut_frac=0.3)
sage: vertex_trunc3.vertices()
(A vertex at (-1.0, -1.0, 1.0),
A vertex at (-1.0, 1.0, -1.0),
A vertex at (-1.0, 1.0, 1.0),
A vertex at (1.0, 1.0, -1.0),
A vertex at (1.0, 1.0, 1.0),
A vertex at (1.0, -1.0, 1.0),
A vertex at (1.0, -1.0, -1.0),
A vertex at (-0.4, -1.0, -1.0),
A vertex at (-1.0, -0.4, -1.0),
A vertex at (-1.0, -1.0, -0.4))
sage: edge_trunc = Cube.face_truncation(Cube.faces(1)[11])
sage: edge_trunc.f_vector()
(1, 10, 15, 7, 1)
sage: tuple(f.ambient_V_indices() for f in edge_trunc.faces(2))
((0, 5, 6, 7),
(1, 4, 5, 6, 8),
(6, 7, 8, 9),
(0, 2, 3, 7, 9),
(1, 2, 8, 9),
(0, 3, 4, 5),
(1, 2, 3, 4))
sage: face_trunc = Cube.face_truncation(Cube.faces(2)[2])
sage: face_trunc.vertices()
(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/3, -1, 1),
A vertex at (-1/3, 1, 1),
A vertex at (-1/3, 1, -1),
A vertex at (-1/3, -1, -1))
sage: face_trunc.face_lattice().is_isomorphic(Cube.face_lattice())
True

intersection(other)#

Return the intersection of one polyhedron with another.

INPUT:

OUTPUT:

The intersection.

Note that the intersection of two $$\ZZ$$-polyhedra might not be a $$\ZZ$$-polyhedron. In this case, a $$\QQ$$-polyhedron is returned.

EXAMPLES:

sage: cube = polytopes.hypercube(3)
sage: oct = polytopes.cross_polytope(3)
sage: cube.intersection(oct*2)
A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 12 vertices


As a shorthand, one may use:

sage: cube & oct*2
A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 12 vertices


The intersection of two $$\ZZ$$-polyhedra is not necessarily a $$\ZZ$$-polyhedron:

sage: P = Polyhedron([(0,0),(1,1)], base_ring=ZZ)
sage: P.intersection(P)
A 1-dimensional polyhedron in ZZ^2 defined as the convex hull of 2 vertices
sage: Q = Polyhedron([(0,1),(1,0)], base_ring=ZZ)
sage: P.intersection(Q)
A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex
sage: _.Vrepresentation()
(A vertex at (1/2, 1/2),)

join(other)#

Return the join of self and other.

The join of two polyhedra is obtained by first placing the two objects in two non-intersecting affine subspaces $$V$$, and $$W$$ whose affine hull is the whole ambient space, and finally by taking the convex hull of their union. The dimension of the join is the sum of the dimensions of the two polyhedron plus 1.

INPUT:

• other – a polyhedron

EXAMPLES:

sage: P1 = Polyhedron([[0],[1]], base_ring=ZZ)
sage: P2 = Polyhedron([[0],[1]], base_ring=QQ)
sage: P1.join(P2)
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices
sage: P1.join(P1)
A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
sage: P2.join(P2)
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices


An unbounded example:

sage: R1 = Polyhedron(rays=[[1]])
sage: R1.join(R1)
A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 2 vertices and 2 rays

lawrence_extension(v)#

Return the Lawrence extension of self on the point v.

Let $$P$$ be a polytope and $$v$$ be a vertex of $$P$$ or a point outside $$P$$. The Lawrence extension of $$P$$ on $$v$$ is the convex hull of $$(v,1),(v,2)$$ and $$(u,0)$$ for all vertices $$u$$ in $$P$$ other than $$v$$ if $$v$$ is a vertex.

INPUT:
• v – a vertex of self or a point outside it

EXAMPLES:

sage: P = polytopes.cube()
sage: P.lawrence_extension(P.vertices()[0])
A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 9 vertices
sage: P.lawrence_extension([-1,-1,-1])
A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 9 vertices


REFERENCES:

lawrence_polytope()#

Return the Lawrence polytope of self.

Let $$P$$ be a $$d$$-polytope in $$\RR^r$$ with $$n$$ vertices. The Lawrence polytope of $$P$$ is the polytope whose vertices are the columns of the following $$(r+n)$$-by-$$2n$$ matrix.

$\begin{split}\begin{pmatrix} V & V \\ I_n & 2I_n \end{pmatrix},\end{split}$

where $$V$$ is the $$r$$-by-$$n$$ vertices matrix of $$P$$.

EXAMPLES:

sage: P = polytopes.octahedron()
sage: L = P.lawrence_polytope(); L
A 9-dimensional polyhedron in ZZ^9 defined as the convex hull of 12 vertices
sage: V = P.vertices_list()
sage: i = 0
sage: for v in V:
....:     v = v + i*[0]
....:     P = P.lawrence_extension(v)
....:     i = i + 1
sage: P == L
True


REFERENCES:

linear_transformation(linear_transf, new_base_ring=None)#

Return the linear transformation of self.

INPUT:

• linear_transf – a matrix, not necessarily in base_ring()

• new_base_ring – ring (optional); specify the new base ring; may avoid coercion failure

OUTPUT:

The polyhedron transformed by that matrix, possibly coerced to a bigger base ring.

EXAMPLES:

sage: b3 = polytopes.Birkhoff_polytope(3)
sage: proj_mat=matrix([[0,1,0,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0],[0,0,0,0,0,1,0,0,0],[0,0,0,0,0,0,0,1,0]])
sage: b3_proj = proj_mat * b3; b3_proj
A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 5 vertices

sage: square = polytopes.regular_polygon(4)                         # optional - sage.rings.number_field
sage: square.vertices_list()                                        # optional - sage.rings.number_field
[[0, -1], [1, 0], [-1, 0], [0, 1]]
sage: transf = matrix([[1,1],[0,1]])                                # optional - sage.rings.number_field
sage: sheared = transf * square                                     # optional - sage.rings.number_field
sage: sheared.vertices_list()                                       # optional - sage.rings.number_field
[[-1, -1], [1, 0], [-1, 0], [1, 1]]
sage: sheared == square.linear_transformation(transf)               # optional - sage.rings.number_field
True


Specifying the new base ring may avoid coercion failure:

sage: K.<sqrt2> = QuadraticField(2)                                 # optional - sage.rings.number_field
sage: L.<sqrt3> = QuadraticField(3)                                 # optional - sage.rings.number_field
sage: P = polytopes.cube()*sqrt2                                    # optional - sage.rings.number_field
sage: M = matrix([[sqrt3, 0, 0], [0, sqrt3, 0], [0, 0, 1]])         # optional - sage.rings.number_field
sage: P.linear_transformation(M, new_base_ring=K.composite_fields(L)[0])   # optional - sage.rings.number_field
A 3-dimensional polyhedron in (Number Field in sqrt2sqrt3 with defining polynomial x^4 - 10*x^2 + 1 with sqrt2sqrt3 = 0.3178372451957823?)^3 defined as the convex hull of 8 vertices


Linear transformation without specified new base ring fails in this case:

sage: M*P                                                           # optional - sage.rings.number_field
Traceback (most recent call last):
...
TypeError: unsupported operand parent(s) for *: 'Full MatrixSpace of 3 by 3 dense matrices over Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?' and 'Full MatrixSpace of 3 by 8 dense matrices over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?'

minkowski_difference(other)#

Return the Minkowski difference.

Minkowski subtraction can equivalently be defined via Minkowski addition (see minkowski_sum()) or as set-theoretic intersection via

$X \ominus Y = (X^c \oplus Y)^c = \bigcap_{y\in Y} (X-y)$

where superscript-“c” means the complement in the ambient vector space. The Minkowski difference of convex sets is convex, and the difference of polyhedra is again a polyhedron. We only consider the case of polyhedra in the following. Note that it is not quite the inverse of addition. In fact:

• $$(X+Y)-Y = X$$ for any polyhedra $$X$$, $$Y$$.

• $$(X-Y)+Y \subseteq X$$

• $$(X-Y)+Y = X$$ if and only if Y is a Minkowski summand of X.

INPUT:

OUTPUT:

The Minkowski difference of self and other. Also known as Minkowski subtraction of other from self.

EXAMPLES:

sage: X = polytopes.hypercube(3)
sage: Y = Polyhedron(vertices=[(0,0,0), (0,0,1), (0,1,0), (1,0,0)]) / 2
sage: (X+Y)-Y == X
True
sage: (X-Y)+Y < X
True


The polyhedra need not be full-dimensional:

sage: X2 = Polyhedron(vertices=[(-1,-1,0),(1,-1,0),(-1,1,0),(1,1,0)])
sage: Y2 = Polyhedron(vertices=[(0,0,0), (0,1,0), (1,0,0)]) / 2
sage: (X2+Y2)-Y2 == X2
True
sage: (X2-Y2)+Y2 < X2
True


Minus sign is really an alias for minkowski_difference()

sage: four_cube = polytopes.hypercube(4)
sage: four_simplex = Polyhedron(vertices = [[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]])
sage: four_cube - four_simplex
A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 16 vertices
sage: four_cube.minkowski_difference(four_simplex) == four_cube - four_simplex
True


Coercion of the base ring works:

sage: poly_spam = Polyhedron([[3,4,5,2],[1,0,0,1],[0,0,0,0],[0,4,3,2],[-3,-3,-3,-3]], base_ring=ZZ)
sage: poly_eggs = Polyhedron([[5,4,5,4],[-4,5,-4,5],[4,-5,4,-5],[0,0,0,0]], base_ring=QQ) / 100
sage: poly_spam - poly_eggs
A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices

minkowski_sum(other)#

Return the Minkowski sum.

Minkowski addition of two subsets of a vector space is defined as

$X \oplus Y = \bigcup_{y\in Y} (X+y) = \bigcup_{x\in X, y\in Y} (x+y)$

See minkowski_difference() for a partial inverse operation.

INPUT:

OUTPUT:

The Minkowski sum of self and other

EXAMPLES:

sage: X = polytopes.hypercube(3)
sage: Y = Polyhedron(vertices=[(0,0,0), (0,0,1/2), (0,1/2,0), (1/2,0,0)])
sage: X+Y
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 13 vertices

sage: four_cube = polytopes.hypercube(4)
sage: four_simplex = Polyhedron(vertices = [[0, 0, 0, 1], [0, 0, 1, 0], [0, 1, 0, 0], [1, 0, 0, 0]])
sage: four_cube + four_simplex
A 4-dimensional polyhedron in ZZ^4 defined as the convex hull of 36 vertices
sage: four_cube.minkowski_sum(four_simplex) == four_cube + four_simplex
True

sage: poly_spam = Polyhedron([[3,4,5,2],[1,0,0,1],[0,0,0,0],[0,4,3,2],[-3,-3,-3,-3]], base_ring=ZZ)
sage: poly_eggs = Polyhedron([[5,4,5,4],[-4,5,-4,5],[4,-5,4,-5],[0,0,0,0]], base_ring=QQ)
sage: poly_spam + poly_spam + poly_eggs
A 4-dimensional polyhedron in QQ^4 defined as the convex hull of 12 vertices

one_point_suspension(vertex)#

Return the one-point suspension of self by splitting the vertex vertex.

The resulting polyhedron has one more vertex and its dimension increases by one.

INPUT:

• vertex – a Vertex of self

EXAMPLES:

sage: cube = polytopes.cube()
sage: v = cube.vertices()[0]
sage: ops_cube = cube.one_point_suspension(v)
sage: ops_cube.f_vector()
(1, 9, 24, 24, 9, 1)

sage: pentagon  = polytopes.regular_polygon(5)                      # optional - sage.rings.number_field
sage: v = pentagon.vertices()[0]                                    # optional - sage.rings.number_field
sage: ops_pentagon = pentagon.one_point_suspension(v)               # optional - sage.rings.number_field
sage: ops_pentagon.f_vector()                                       # optional - sage.rings.number_field
(1, 6, 12, 8, 1)


It works with a polyhedral face as well:

sage: vv = cube.faces(0)[1]
sage: ops_cube2 = cube.one_point_suspension(vv)
sage: ops_cube == ops_cube2
True

polar(in_affine_span=False)#

Return the polar (dual) polytope.

The original vertices are translated so that their barycenter is at the origin, and then the vertices are used as the coefficients in the polar inequalities.

The polytope must be full-dimensional, unless in_affine_span is True. If in_affine_span is True, then the operation will be performed in the linear/affine span of the polyhedron (after translation).

EXAMPLES:

sage: p = Polyhedron(vertices = [[0,0,1],[0,1,0],[1,0,0],[0,0,0],[1,1,1]], base_ring=QQ)
sage: p
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 5 vertices
sage: p.polar()
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 6 vertices

sage: cube = polytopes.hypercube(3)
sage: octahedron = polytopes.cross_polytope(3)
sage: cube_dual = cube.polar()
sage: octahedron == cube_dual
True


in_affine_span somewhat ignores equations, performing the polar in the spanned subspace (after translating barycenter to origin):

sage: P = polytopes.simplex(3, base_ring=QQ)
sage: P.polar(in_affine_span=True)
A 3-dimensional polyhedron in QQ^4 defined as the convex hull of 4 vertices


Embedding the polytope in a higher dimension, commutes with polar in this case:

sage: point = Polyhedron([[0]])
sage: P = polytopes.cube().change_ring(QQ)
sage: (P*point).polar(in_affine_span=True) == P.polar()*point
True

prism()#

Return a prism of the original polyhedron.

EXAMPLES:

sage: square = polytopes.hypercube(2)
sage: cube = square.prism()
sage: cube
A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices
sage: hypercube = cube.prism()
sage: hypercube.n_vertices()
16

product(other)#

Return the Cartesian product.

INPUT:

OUTPUT:

The Cartesian product of self and other with a suitable base ring to encompass the two.

EXAMPLES:

sage: P1 = Polyhedron([[0],[1]], base_ring=ZZ)
sage: P2 = Polyhedron([[0],[1]], base_ring=QQ)
sage: P1.product(P2)
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices


The Cartesian product is the product in the semiring of polyhedra:

sage: P1 * P1
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices
sage: P1 * P2
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
sage: P2 * P2
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices
sage: 2 * P1
A 1-dimensional polyhedron in ZZ^1 defined as the convex hull of 2 vertices
sage: P1 * 2.0
A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices


An alias is cartesian_product():

sage: P1.cartesian_product(P2) == P1.product(P2)
True

pyramid()#

Return a polyhedron that is a pyramid over the original.

EXAMPLES:

sage: square = polytopes.hypercube(2);  square
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices
sage: egyptian_pyramid = square.pyramid();  egyptian_pyramid
A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 5 vertices
sage: egyptian_pyramid.n_vertices()
5
sage: for v in egyptian_pyramid.vertex_generator(): print(v)
A vertex at (0, -1, -1)
A vertex at (0, -1, 1)
A vertex at (0, 1, -1)
A vertex at (0, 1, 1)
A vertex at (1, 0, 0)

stack(face, position=None)#

Return a new polyhedron formed by stacking onto a face. Stacking a face adds a new vertex located slightly outside of the designated face.

INPUT:

• face – a PolyhedronFace

• position – a positive number. Determines a relative distance from the barycenter of face. A value close to 0 will place the new vertex close to the face and a large value further away. Default is $$1$$. If the given value is too large, an error is returned.

OUTPUT:

A Polyhedron object

EXAMPLES:

sage: cube = polytopes.cube()
sage: square_face = cube.facets()[2]
sage: stacked_square = cube.stack(square_face)
sage: stacked_square.f_vector()
(1, 9, 16, 9, 1)

sage: edge_face = cube.faces(1)[3]
sage: stacked_edge = cube.stack(edge_face)
sage: stacked_edge.f_vector()
(1, 9, 17, 10, 1)

sage: cube.stack(cube.faces(0)[0])
Traceback (most recent call last):
...
ValueError: cannot stack onto a vertex

sage: stacked_square_half = cube.stack(square_face,position=1/2)
sage: stacked_square_half.f_vector()
(1, 9, 16, 9, 1)
sage: stacked_square_large = cube.stack(square_face,position=10)

sage: hexaprism = polytopes.regular_polygon(6).prism()              # optional - sage.rings.number_field
sage: hexaprism.f_vector()                                          # optional - sage.rings.number_field
(1, 12, 18, 8, 1)
sage: square_face = hexaprism.faces(2)[2]                           # optional - sage.rings.number_field
sage: stacked_hexaprism = hexaprism.stack(square_face)              # optional - sage.rings.number_field
sage: stacked_hexaprism.f_vector()                                  # optional - sage.rings.number_field
(1, 13, 22, 11, 1)

sage: hexaprism.stack(square_face,position=4)                       # optional - sage.rings.number_field
Traceback (most recent call last):
...
ValueError: the chosen position is too large

sage: s = polytopes.simplex(7)
sage: f = s.faces(3)[69]
sage: sf = s.stack(f); sf
A 7-dimensional polyhedron in QQ^8 defined as the convex hull of 9 vertices
sage: sf.vertices()
(A vertex at (-4, -4, -4, -4, 17/4, 17/4, 17/4, 17/4),
A vertex at (0, 0, 0, 0, 0, 0, 0, 1),
A vertex at (0, 0, 0, 0, 0, 0, 1, 0),
A vertex at (0, 0, 0, 0, 0, 1, 0, 0),
A vertex at (0, 0, 0, 0, 1, 0, 0, 0),
A vertex at (0, 0, 0, 1, 0, 0, 0, 0),
A vertex at (0, 0, 1, 0, 0, 0, 0, 0),
A vertex at (0, 1, 0, 0, 0, 0, 0, 0),
A vertex at (1, 0, 0, 0, 0, 0, 0, 0))


It is possible to stack on unbounded faces:

sage: Q = Polyhedron(vertices=[[0,1],[1,0]],rays=[[1,1]])
sage: E = Q.faces(1)
sage: Q.stack(E[0],1/2).Vrepresentation()
(A vertex at (0, 1),
A vertex at (1, 0),
A ray in the direction (1, 1),
A vertex at (2, 0))
sage: Q.stack(E[1],1/2).Vrepresentation()
(A vertex at (0, 1),
A vertex at (0, 2),
A vertex at (1, 0),
A ray in the direction (1, 1))
sage: Q.stack(E[2],1/2).Vrepresentation()
(A vertex at (0, 0),
A vertex at (0, 1),
A vertex at (1, 0),
A ray in the direction (1, 1))


Stacking requires a proper face:

sage: Q.stack(Q.faces(2)[0])
Traceback (most recent call last):
...
ValueError: can only stack on proper face

subdirect_sum(other)#

Return the subdirect sum of self and other.

The subdirect sum of two polyhedron is a projection of the join of the two polytopes. It is obtained by placing the two objects in orthogonal subspaces intersecting at the origin.

INPUT:

EXAMPLES:

sage: P1 = Polyhedron([[1],[2]], base_ring=ZZ)
sage: P2 = Polyhedron([[3],[4]], base_ring=QQ)
sage: sds = P1.subdirect_sum(P2);sds
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4
vertices
sage: sds.vertices()
(A vertex at (0, 3),
A vertex at (0, 4),
A vertex at (1, 0),
A vertex at (2, 0))

translation(displacement)#

Return the translated polyhedron.

INPUT:

• displacement – a displacement vector or a list/tuple of coordinates that determines a displacement vector

OUTPUT:

The translated polyhedron.

EXAMPLES:

sage: P = Polyhedron([[0,0],[1,0],[0,1]], base_ring=ZZ)
sage: P.translation([2,1])
A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices
sage: P.translation( vector(QQ,[2,1]) )
A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 3 vertices

truncation(cut_frac=None)#

Return a new polyhedron formed from two points on each edge between two vertices.

INPUT:

• cut_frac – integer, how deeply to cut into the edge. Default is $$\frac{1}{3}$$.

OUTPUT:

A Polyhedron object, truncated as described above.

EXAMPLES:

sage: cube = polytopes.hypercube(3)
sage: trunc_cube = cube.truncation()
sage: trunc_cube.n_vertices()
24
sage: trunc_cube.n_inequalities()
14

wedge(face, width=1)#

Return the wedge over a face of the polytope self.

The wedge over a face $$F$$ of a polytope $$P$$ with width $$w \not= 0$$ is defined as:

$(P \times \mathbb{R}) \cap \{a^\top x + |w x_{d+1}| \leq b\}$

where $$\{x | a^\top x = b\}$$ is a supporting hyperplane defining $$F$$.

INPUT:

• face – a PolyhedronFace of self, the face which we take the wedge over

• width – a nonzero number (default: 1); specifies how wide the wedge will be

OUTPUT:

A (bounded) polyhedron

EXAMPLES:

sage: P_4 = polytopes.regular_polygon(4)                                              # optional - sage.rings.number_field
sage: W1 = P_4.wedge(P_4.faces(1)[0]); W1                                             # optional - sage.rings.number_field
A 3-dimensional polyhedron in AA^3 defined as the convex hull of 6 vertices
sage: triangular_prism = polytopes.regular_polygon(3).prism()                         # optional - sage.rings.number_field
sage: W1.is_combinatorially_isomorphic(triangular_prism)  # optional - sage.graphs    # optional - sage.rings.number_field
True

sage: Q = polytopes.hypersimplex(4,2)
sage: W2 = Q.wedge(Q.faces(2)[7]); W2
A 4-dimensional polyhedron in QQ^5 defined as the convex hull of 9 vertices
sage: W2.vertices()
(A vertex at (1, 1, 0, 0, 1),
A vertex at (1, 1, 0, 0, -1),
A vertex at (1, 0, 1, 0, 1),
A vertex at (1, 0, 1, 0, -1),
A vertex at (1, 0, 0, 1, 1),
A vertex at (1, 0, 0, 1, -1),
A vertex at (0, 0, 1, 1, 0),
A vertex at (0, 1, 1, 0, 0),
A vertex at (0, 1, 0, 1, 0))

sage: W3 = Q.wedge(Q.faces(1)[11]); W3
A 4-dimensional polyhedron in QQ^5 defined as the convex hull of 10 vertices
sage: W3.vertices()
(A vertex at (1, 1, 0, 0, -2),
A vertex at (1, 1, 0, 0, 2),
A vertex at (1, 0, 1, 0, -2),
A vertex at (1, 0, 1, 0, 2),
A vertex at (1, 0, 0, 1, 1),
A vertex at (1, 0, 0, 1, -1),
A vertex at (0, 1, 0, 1, 0),
A vertex at (0, 1, 1, 0, 1),
A vertex at (0, 0, 1, 1, 0),
A vertex at (0, 1, 1, 0, -1))

sage: C_3_7 = polytopes.cyclic_polytope(3,7)
sage: P_6 = polytopes.regular_polygon(6)                                              # optional - sage.rings.number_field
sage: W4 = P_6.wedge(P_6.faces(1)[0])                                                 # optional - sage.rings.number_field
sage: W4.is_combinatorially_isomorphic(C_3_7.polar())     # optional - sage.graphs    # optional - sage.rings.number_field
True


REFERENCES: