Base class for polyhedra over #
- class sage.geometry.polyhedron.base_QQ.Polyhedron_QQ(parent, Vrep, Hrep, Vrep_minimal=None, Hrep_minimal=None, pref_rep=None, mutable=False, **kwds)#
Bases:
Polyhedron_base
Base class for Polyhedra over
- Hstar_function(acting_group=None, output=None)#
Return
as a rational function in with coefficients in the ring of class functions of theacting_group
of this polytope.Here,
. The irreducible characters ofacting_group
form an orthonormal basis for the ring of class functions with values in . The coefficients of are expressed in this basis.INPUT:
acting_group
– (default=None) a permgroup object. A subgroup of the polytope’srestricted_automorphism_group
. IfNone
, it is set to the fullrestricted_automorphism_group
of the polytope. The acting group should always use output=’permutation’.output
– string. an output option. The allowed values are:None
(default): returns the rational function . is a rational function in with coefficients in the ring of class functions.'e_series_list'
: Returns a list of the ehrhart_series for the fixed_subpolytopes of each conjugacy class representative.'determinant_vec'
: Returns a list of the determinants of for each conjugacy class representative.'Hstar_as_lin_comb'
: Returns a vector of the coefficients of the irreducible representations in the expression of .'prod_det_es'
: Returns a vector of the product of determinants and the Ehrhart series.'complete'
: Returns a list with Hstar, Hstar_as_lin_comb, character table of the acting group, and whether Hstar is effective.
OUTPUT:
The default output is the rational function
. is a rational function in with coefficients in the ring of class functions. There are several output options to see the intermediary outputs of the function.EXAMPLES:
The
-polynomial of the standard ( )-dimensional simplex under itsrestricted_automorphism_group
is equal to 1 = (Prop 6.1 [Stap2011]). Here is the computation for the 3-dimensional standard simplex:sage: S = polytopes.simplex(3, backend = 'normaliz'); S # optional - pynormaliz A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 4 vertices sage: G = S.restricted_automorphism_group(output = 'permutation') # optional - pynormaliz sage: G.is_isomorphic(SymmetricGroup(4)) # optional - pynormaliz True sage: Hstar = S._Hstar_function_normaliz(G); Hstar # optional - pynormaliz chi_4 sage: G.character_table() # optional - pynormaliz [ 1 -1 1 1 -1] [ 3 -1 0 -1 1] [ 2 0 -1 2 0] [ 3 1 0 -1 -1] [ 1 1 1 1 1]
The next example is Example 7.6 in [Stap2011], and shows that
is not always a polynomial. Let P be the polytope with vertices and let G = act on P as follows:sage: P = Polyhedron(vertices=[[0,0,1],[0,0,-1],[1,0,1],[-1,0,-1],[0,1,1], # optional - pynormaliz ....: [0,-1,-1],[1,1,1],[-1,-1,-1]],backend='normaliz') # optional - pynormaliz sage: K = P.restricted_automorphism_group(output = 'permutation') # optional - pynormaliz sage: G = K.subgroup(gens = [K([(0,2),(1,3),(4,6),(5,7)])]) # optional - pynormaliz sage: conj_reps = G.conjugacy_classes_representatives() # optional - pynormaliz sage: Dict = P.permutations_to_matrices(conj_reps, acting_group = G) # optional - pynormaliz sage: list(Dict.keys())[0] # optional - pynormaliz (0,2)(1,3)(4,6)(5,7) sage: list(Dict.values())[0] # optional - pynormaliz [-1 0 1 0] [ 0 1 0 0] [ 0 0 1 0] [ 0 0 0 1] sage: len(G) # optional - pynormaliz 2 sage: G.character_table() # optional - pynormaliz [ 1 1] [ 1 -1]
Then we calculate the rational function
:sage: Hst = P._Hstar_function_normaliz(G); Hst # optional - pynormaliz (chi_0*t^4 + (3*chi_0 + 3*chi_1)*t^3 + (8*chi_0 + 2*chi_1)*t^2 + (3*chi_0 + 3*chi_1)*t + chi_0)/(t + 1)
To see the exact as written in [Stap2011], we can format it as
'Hstar_as_lin_comb'
. The first coordinate is the coefficient of the trivial character; the second is the coefficient of the sign character:sage: lin = P._Hstar_function_normaliz(G,output = 'Hstar_as_lin_comb'); lin # optional - pynormaliz ((t^4 + 3*t^3 + 8*t^2 + 3*t + 1)/(t + 1), (3*t^3 + 2*t^2 + 3*t)/(t + 1))
- ehrhart_polynomial(engine=None, variable='t', verbose=False, dual=None, irrational_primal=None, irrational_all_primal=None, maxdet=None, no_decomposition=None, compute_vertex_cones=None, smith_form=None, dualization=None, triangulation=None, triangulation_max_height=None, **kwds)#
Return the Ehrhart polynomial of this polyhedron.
The polyhedron must be a lattice polytope. Let
be a lattice polytope in and define . Then E. Ehrhart proved in 1962 that coincides with a rational polynomial of degree for integer . is called the Ehrhart polynomial of . For more information see the Wikipedia article Ehrhart_polynomial. The Ehrhart polynomial may be computed using either LattE Integrale or Normaliz by settingengine
to ‘latte’ or ‘normaliz’ respectively.INPUT:
engine
– string; The backend to use. Allowed values are:None
(default); When no input is given the Ehrhart polynomial is computed using LattE Integrale (optional)'latte'
; use LattE integrale program (optional)'normaliz'
; use Normaliz program (optional package pynormaliz). The backend ofself
must be set to ‘normaliz’.
variable
– string (default: ‘t’); The variable in which the Ehrhart polynomial should be expressed.When the
engine
is ‘latte’, the additional input values are:verbose
- boolean (default:False
); IfTrue
, print the whole output of the LattE command.
The following options are passed to the LattE command, for details consult the LattE documentation:
dual
- boolean; triangulate and signed-decompose in the dual spaceirrational_primal
- boolean; triangulate in the dual space, signed-decompose in the primal space using irrationalization.irrational_all_primal
- boolean; triangulate and signed-decompose in the primal space using irrationalization.maxdet
– integer; decompose down to an index (determinant) ofmaxdet
instead of index 1 (unimodular cones).no_decomposition
– boolean; do not signed-decompose simplicial cones.compute_vertex_cones
– string; either ‘cdd’ or ‘lrs’ or ‘4ti2’smith_form
– string; either ‘ilio’ or ‘lidia’dualization
– string; either ‘cdd’ or ‘4ti2’triangulation
- string; ‘cddlib’, ‘4ti2’ or ‘topcom’triangulation_max_height
- integer; use a uniform distribution of height from 1 to this number
OUTPUT:
A univariate polynomial in
variable
over a rational field.See also
latte
the interface to LattE Integrale PyNormalizEXAMPLES:
To start, we find the Ehrhart polynomial of a three-dimensional
simplex
, first usingengine='latte'
. Leaving the engine unspecified sets theengine
to ‘latte’ by default:sage: simplex = Polyhedron(vertices=[(0,0,0),(3,3,3),(-3,2,1),(1,-1,-2)]) sage: simplex = simplex.change_ring(QQ) sage: poly = simplex.ehrhart_polynomial(engine='latte') # optional - latte_int sage: poly # optional - latte_int 7/2*t^3 + 2*t^2 - 1/2*t + 1 sage: poly(1) # optional - latte_int 6 sage: len(simplex.integral_points()) # optional - latte_int 6 sage: poly(2) # optional - latte_int 36 sage: len((2*simplex).integral_points()) # optional - latte_int 36
Now we find the same Ehrhart polynomial, this time using
engine='normaliz'
. To use the Normaliz engine, thesimplex
must be defined withbackend='normaliz'
:sage: simplex = Polyhedron(vertices=[(0,0,0),(3,3,3),(-3,2,1),(1,-1,-2)], backend='normaliz') # optional - pynormaliz sage: simplex = simplex.change_ring(QQ) # optional - pynormaliz sage: poly = simplex.ehrhart_polynomial(engine = 'normaliz') # optional - pynormaliz sage: poly # optional - pynormaliz 7/2*t^3 + 2*t^2 - 1/2*t + 1
If the
engine='normaliz'
, the backend should be'normaliz'
, otherwise it returns an error:sage: simplex = Polyhedron(vertices=[(0,0,0),(3,3,3),(-3,2,1),(1,-1,-2)]) sage: simplex = simplex.change_ring(QQ) sage: simplex.ehrhart_polynomial(engine='normaliz') # optional - pynormaliz Traceback (most recent call last): ... TypeError: The backend of the polyhedron should be 'normaliz'
The polyhedron should be compact:
sage: C = Polyhedron(backend='normaliz',rays=[[1,2],[2,1]]) # optional - pynormaliz sage: C = C.change_ring(QQ) # optional - pynormaliz sage: C.ehrhart_polynomial() # optional - pynormaliz Traceback (most recent call last): ... ValueError: Ehrhart polynomial only defined for compact polyhedra
The polyhedron should have integral vertices:
sage: L = Polyhedron(vertices = [[0],[1/2]]) sage: L.ehrhart_polynomial() Traceback (most recent call last): ... TypeError: the polytope has nonintegral vertices, use ehrhart_quasipolynomial with backend 'normaliz'
- ehrhart_quasipolynomial(variable='t', engine=None, verbose=False, dual=None, irrational_primal=None, irrational_all_primal=None, maxdet=None, no_decomposition=None, compute_vertex_cones=None, smith_form=None, dualization=None, triangulation=None, triangulation_max_height=None, **kwds)#
Compute the Ehrhart quasipolynomial of this polyhedron with rational vertices.
If the polyhedron is a lattice polytope, returns the Ehrhart polynomial, a univariate polynomial in
variable
over a rational field. If the polyhedron has rational, nonintegral vertices, returns a tuple of polynomials invariable
over a rational field. The Ehrhart counting function of a polytope with rational vertices is given by a quasipolynomial. That is, there exists a positive integer and polynomials such that if is equivalent to mod then .INPUT:
variable
– string (default: ‘t’); The variable in which the Ehrhart polynomial should be expressed.engine
– string; The backend to use. Allowed values are:None
(default); When no input is given the Ehrhart polynomial is computed using Normaliz (optional)'latte'
; use LattE Integrale program (requires optional package ‘latte_int’)'normaliz'
; use the Normaliz program (requires optional package ‘pynormaliz’). The backend ofself
must be set to ‘normaliz’.
When the
engine
is ‘latte’, the additional input values are:verbose
- boolean (default:False
); IfTrue
, print the whole output of the LattE command.
The following options are passed to the LattE command, for details consult the LattE documentation:
dual
- boolean; triangulate and signed-decompose in the dual spaceirrational_primal
- boolean; triangulate in the dual space, signed-decompose in the primal space using irrationalization.irrational_all_primal
- boolean; triangulate and signed-decompose in the primal space using irrationalization.maxdet
– integer; decompose down to an index (determinant) ofmaxdet
instead of index 1 (unimodular cones).no_decomposition
– boolean; do not signed-decompose simplicial cones.compute_vertex_cones
– string; either ‘cdd’ or ‘lrs’ or ‘4ti2’smith_form
– string; either ‘ilio’ or ‘lidia’dualization
– string; either ‘cdd’ or ‘4ti2’triangulation
- string; ‘cddlib’, ‘4ti2’ or ‘topcom’triangulation_max_height
- integer; use a uniform distribution of height from 1 to this number
OUTPUT:
A univariate polynomial over a rational field or a tuple of such polynomials.
See also
latte
the interface to LattE Integrale PyNormalizWarning
If the polytope has rational, non integral vertices, it must have
backend='normaliz'
.EXAMPLES:
As a first example, consider the line segment [0,1/2]. If we dilate this line segment by an even integral factor
, then the dilated line segment will contain lattice points. If is odd then there will be lattice points in the dilated line segment. Note that it is necessary to set the backend of the polytope to ‘normaliz’:sage: line_seg = Polyhedron(vertices=[[0],[1/2]],backend='normaliz') # optional - pynormaliz sage: line_seg # optional - pynormaliz A 1-dimensional polyhedron in QQ^1 defined as the convex hull of 2 vertices sage: line_seg.ehrhart_quasipolynomial() # optional - pynormaliz (1/2*t + 1, 1/2*t + 1/2)
For a more exciting example, let us look at the subpolytope of the 3 dimensional permutahedron fixed by the reflection across the hyperplane
:sage: verts = [[3/2, 3, 4, 3/2], ....: [3/2, 4, 3, 3/2], ....: [5/2, 1, 4, 5/2], ....: [5/2, 4, 1, 5/2], ....: [7/2, 1, 2, 7/2], ....: [7/2, 2, 1, 7/2]] sage: subpoly = Polyhedron(vertices=verts, backend='normaliz') # optional - pynormaliz sage: eq = subpoly.ehrhart_quasipolynomial() # optional - pynormaliz sage: eq # optional - pynormaliz (4*t^2 + 3*t + 1, 4*t^2 + 2*t) sage: eq = subpoly.ehrhart_quasipolynomial() # optional - pynormaliz sage: eq # optional - pynormaliz (4*t^2 + 3*t + 1, 4*t^2 + 2*t) sage: even_ep = eq[0] # optional - pynormaliz sage: odd_ep = eq[1] # optional - pynormaliz sage: even_ep(2) # optional - pynormaliz 23 sage: ts = 2*subpoly # optional - pynormaliz sage: ts.integral_points_count() # optional - pynormaliz latte_int 23 sage: odd_ep(1) # optional - pynormaliz 6 sage: subpoly.integral_points_count() # optional - pynormaliz latte_int 6
A polytope with rational nonintegral vertices must have
backend='normaliz'
:sage: line_seg = Polyhedron(vertices=[[0],[1/2]]) sage: line_seg.ehrhart_quasipolynomial() Traceback (most recent call last): ... TypeError: The backend of the polyhedron should be 'normaliz'
The polyhedron should be compact:
sage: C = Polyhedron(backend='normaliz',rays=[[1/2,2],[2,1]]) # optional - pynormaliz sage: C.ehrhart_quasipolynomial() # optional - pynormaliz Traceback (most recent call last): ... ValueError: Ehrhart quasipolynomial only defined for compact polyhedra
If the polytope happens to be a lattice polytope, the Ehrhart polynomial is returned:
sage: simplex = Polyhedron(vertices=[(0,0,0),(3,3,3),(-3,2,1),(1,-1,-2)], backend='normaliz') # optional - pynormaliz sage: simplex = simplex.change_ring(QQ) # optional - pynormaliz sage: poly = simplex.ehrhart_quasipolynomial(engine='normaliz') # optional - pynormaliz sage: poly # optional - pynormaliz 7/2*t^3 + 2*t^2 - 1/2*t + 1 sage: simplex.ehrhart_polynomial() # optional - pynormaliz latte_int 7/2*t^3 + 2*t^2 - 1/2*t + 1
- fixed_subpolytope(vertex_permutation)#
Return the fixed subpolytope of this polytope by the cyclic action of
vertex_permutation
.The fixed subpolytope of this polytope under the
vertex_permutation
is the subset of this polytope that is fixed pointwise.INPUT:
vertex_permutation
– permutation; a permutation of the vertices ofself
.
OUTPUT:
A subpolytope of
self
.Note
The vertex_permutation is obtained as a permutation of the vertices represented as a permutation. For example, vertex_permutation = self.restricted_automorphism_group(output=’permutation’).
Requiring a lattice polytope as opposed to a rational polytope as input is purely conventional.
EXAMPLES:
The fixed subpolytopes of the cube can be obtained as follows:
sage: Cube = polytopes.cube(backend = 'normaliz') # optional - pynormaliz sage: AG = Cube.restricted_automorphism_group(output='permutation') # optional - pynormaliz sage: reprs = AG.conjugacy_classes_representatives() # optional - pynormaliz
The fixed subpolytope of the identity element of the group is the entire cube:
sage: reprs[0] # optional - pynormaliz () sage: Cube.fixed_subpolytope(vertex_permutation = reprs[0]) # optional - pynormaliz A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 8 vertices sage: _.vertices() # optional - pynormaliz (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))
You can obtain non-trivial examples:
sage: fsp = Cube.fixed_subpolytope(AG([(0,1),(2,3),(4,5),(6,7)]));fsp # optional - pynormaliz A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 4 vertices sage: fsp.vertices() # optional - pynormaliz (A vertex at (-1, -1, 0), A vertex at (-1, 1, 0), A vertex at (1, -1, 0), A vertex at (1, 1, 0))
The next example shows that fixed_subpolytope works for rational polytopes:
sage: P = Polyhedron(vertices=[[0],[1/2]], backend='normaliz') # optional - pynormaliz sage: P.vertices() # optional - pynormaliz (A vertex at (0), A vertex at (1/2)) sage: G = P.restricted_automorphism_group(output='permutation');G # optional - pynormaliz Permutation Group with generators [(0,1)] sage: len(G) # optional - pynormaliz 2 sage: fixed_set = P.fixed_subpolytope(G.gens()[0]); fixed_set # optional - pynormaliz A 0-dimensional polyhedron in QQ^1 defined as the convex hull of 1 vertex sage: fixed_set.vertices_list() # optional - pynormaliz [[1/4]]
- fixed_subpolytopes(conj_class_reps)#
Return the fixed subpolytopes of this polytope under the actions of the given conjugacy class representatives.
The
conj_class_reps
are representatives of the conjugacy classes of a subgroup of the automorphism group of this polytope. For an element of the automorphism group, the fixed subpolytope is the subset of this polytope that is fixed pointwise.INPUT:
conj_class_reps
– a list of representatives of the conjugacy classes of the subgroup of therestricted_automorphism_group
of the polytope. Each element is written as a permutation of the vertices of the polytope.
OUTPUT:
A dictionary where the elements of
conj_class_reps
are keys and the fixed subpolytopes are values.Note
Two elements in the same conjugacy class fix lattice-isomorphic subpolytopes.
EXAMPLES:
Here is an example for the square:
sage: p = polytopes.hypercube(2, backend = 'normaliz'); p # optional - pynormaliz A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 4 vertices sage: aut_p = p.restricted_automorphism_group(output = 'permutation') # optional - pynormaliz sage: aut_p.order() # optional - pynormaliz 8 sage: conj_list = aut_p.conjugacy_classes_representatives(); # optional - pynormaliz sage: fixedpolytopes_dictionary = p.fixed_subpolytopes(conj_list) # optional - pynormaliz sage: fixedpolytopes_dictionary[aut_p([(0,3),(1,2)])] # optional - pynormaliz A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex
- integral_points_count(verbose=False, use_Hrepresentation=False, explicit_enumeration_threshold=1000, preprocess=True, **kwds)#
Return the number of integral points in the polyhedron.
This method uses the optional package
latte_int
if an estimate for lattice points based on bounding boxes exceedsexplicit_enumeration_threshold
.INPUT:
verbose
(boolean;False
by default) – whether to display verbose output.use_Hrepresentation
- (boolean;False
by default) – whether to send the H or V representation to LattEpreprocess
- (boolean;True
by default) – whether, if the integral hull is known to lie in a coordinate hyperplane, to tighten bounds to reduce dimension
See also
latte
the interface to LattE interfacesEXAMPLES:
sage: P = polytopes.cube() sage: P.integral_points_count() 27 sage: P.integral_points_count(explicit_enumeration_threshold=0) # optional - latte_int 27
We enlarge the polyhedron to force the use of the generating function methods implemented in LattE integrale, rather than explicit enumeration.
sage: (1000000000*P).integral_points_count(verbose=True) # optional - latte_int This is LattE integrale… … Total time:… 8000000012000000006000000001
We shrink the polyhedron a little bit:
sage: Q = P*(8/9) sage: Q.integral_points_count() 1 sage: Q.integral_points_count(explicit_enumeration_threshold=0) # optional - latte_int 1
Unbounded polyhedra (with or without lattice points) are not supported:
sage: P = Polyhedron(vertices=[[1/2, 1/3]], rays=[[1, 1]]) sage: P.integral_points_count() Traceback (most recent call last): ... NotImplementedError: ... sage: P = Polyhedron(vertices=[[1, 1]], rays=[[1, 1]]) sage: P.integral_points_count() Traceback (most recent call last): ... NotImplementedError: ...
“Fibonacci” knapsacks (preprocessing helps a lot):
sage: def fibonacci_knapsack(d, b, backend=None): ....: lp = MixedIntegerLinearProgram(base_ring=QQ) ....: x = lp.new_variable(nonnegative=True) ....: lp.add_constraint(lp.sum(fibonacci(i+3)*x[i] for i in range(d)) <= b) ....: return lp.polyhedron(backend=backend) sage: fibonacci_knapsack(20, 12).integral_points_count() # does not finish with preprocess=False 33
- is_effective(Hstar, Hstar_as_lin_comb)#
Test for the effectiveness of the
Hstar
series of this polytope.The
Hstar
series of the polytope is determined by the action of a subgroup of the polytope’srestricted_automorphism_group
. TheHstar
series is effective if it is a polynomial in and the coefficient of each is an effective character in the ring of class functions of the acting group. A character is effective if the coefficients of the irreducible representations in the expression of are non-negative integers.INPUT:
Hstar
– a rational function in with coefficients in the ring of class functions.Hstar_as_lin_comb
– vector. The coefficients of the irreducible representations of the acting group in the expression ofHstar
as a linear combination of irreducible representations with coefficients in the field of rational functions in .
OUTPUT:
Boolean. Whether the
Hstar
series is effective.See also
EXAMPLES:
The
series of the two-dimensional permutahedron under the action of the symmetric group is effective:sage: p3 = polytopes.permutahedron(3, backend = 'normaliz') # optional - pynormaliz sage: G = p3.restricted_automorphism_group(output='permutation') # optional - pynormaliz sage: reflection12 = G([(0,2),(1,4),(3,5)]) # optional - pynormaliz sage: reflection23 = G([(0,1),(2,3),(4,5)]) # optional - pynormaliz sage: S3 = G.subgroup(gens=[reflection12, reflection23]) # optional - pynormaliz sage: S3.is_isomorphic(SymmetricGroup(3)) # optional - pynormaliz True sage: [Hstar, Hlin] = [p3.Hstar_function(S3), p3.Hstar_function(S3, output = 'Hstar_as_lin_comb')] # optional - pynormaliz sage: p3.is_effective(Hstar,Hlin) # optional - pynormaliz True
If the
-series is not polynomial, then it is not effective:sage: P = Polyhedron(vertices=[[0,0,1],[0,0,-1],[1,0,1],[-1,0,-1],[0,1,1], # optional - pynormaliz ....: [0,-1,-1],[1,1,1],[-1,-1,-1]],backend='normaliz') # optional - pynormaliz sage: G = P.restricted_automorphism_group(output = 'permutation') # optional - pynormaliz sage: H = G.subgroup(gens = [G([(0,2),(1,3),(4,6),(5,7)])]) # optional - pynormaliz sage: Hstar = P.Hstar_function(H); Hstar # optional - pynormaliz (chi_0*t^4 + (3*chi_0 + 3*chi_1)*t^3 + (8*chi_0 + 2*chi_1)*t^2 + (3*chi_0 + 3*chi_1)*t + chi_0)/(t + 1) sage: Hstar_lin = P.Hstar_function(H, output = 'Hstar_as_lin_comb') # optional - pynormaliz sage: P.is_effective(Hstar, Hstar_lin) # optional - pynormaliz False