Module: sage.geometry.lattice_polytope
Lattice and reflexive polytopes
This module provides tools for work with lattice and reflexive
polytopes. A convex polytope is the convex hull of finitely
many points in
. The dimension
of a polytope is the
smallest
such that the polytope can be embedded in
.
A lattice polytope is a polytope whose vertices all have integer coordinates.
If
is a lattice polytope, the dual polytope of
is
A reflexive polytope is a lattice polytope, such that its polar is also a lattice polytope, i.e. has vertices with integer coordinates.
This SAGE module uses Package for Analyzing Lattice Polytopes (PALP), which is a program written in C by Maximilian Kreuzer and Harald Skarke, which is freely available under the GNU licence terms at http://tph16.tuwien.ac.at/~kreuzer/CY/. Moreover, PALP is included standard with SAGE.
PALP is described in the paper math.SC/0204356. Its distribution also contains the application nef.x, which was created by Erwin Riegler and computes nef partitions and Hodge data for toric complete intersections.
ACKNOWLEDGMENT: polytope.py module written by William Stein was used as an example of organizing an interface between an external program and SAGE. William Stein also helped Andrey Novoseltsev with debugging and tuning of this module.
Robert Bradshaw helped Andrey Novoseltsev to realize plot3d function.
IMPORTANT NOTE: PALP requires some parameters to be determined during compilation time, i.e., the maximum dimension of polytopes, the maximum number of points, etc. These limitations may lead to errors during calls to different functions of these module. Currently, a ValueError exception will be raised if the output of poly.x or nef.x is empty or contains the exclamation mark. The error message will contain the exact command that caused an error, the description and vertices of the polytope, and the obtained output.
Data obtained from PALP and some other data is cached and most returned values are immutable. In particular, you cannot change the vertices of the polytope or their order after creation of the polytope.
If you are going to work with large sets of data, take a look at all_* functions in this module. They precompute different data for sequences of polynomials with a few runs of external programs. This can significantly affect the time of future computations. You can also use dump/load, but not all data will be stored (currently only faces and the number of their internal and boundary points are stored, in addition to polytope vertices and its polar).
Author Log:
- Maximilian Kreuzer and Harald Skarke: authors of PALP (which was also used to obtain the list of 3-dimensional reflexive polytopes) - Erwin Riegler: the author of nef.x
Module-level Functions
data, [desc=None], [compute_vertices=True], [copy_vertices=True], [n=0]) |
Construct a lattice polytope.
LatticePolytope(data, [desc], [compute_vertices], [copy_vertices], [n])
Input:
compute_vertices
is True);
a file with matrix data, open for reading;
or a filename of such a file.
See read_palp_matrix
for the file format.
Points of the given matrix must span the space.
data
is a matrix of vertices, it will be made immutable.
data
is a name of a file, that contains
data blocks for several polytopes, the n-th block will be used.
NUMERATION STARTS WITH ZERO.
Here we construct a polytope from a matrix whose columns are vertices in 3-dimensional space. In the first case a copy of the given matrix is made during construction, in the second one the matrix is made immutable and used as a matrix of vertices.
sage: m = matrix(ZZ, [[1, 0, 0, -1, 0, 0], ... [0, 1, 0, 0, -1, 0], ... [0, 0, 1, 0, 0, -1]]) ... sage: p = LatticePolytope(m) sage: p A lattice polytope: 3-dimensional, 6 vertices. sage: m.is_mutable() True sage: m is p.vertices() False sage: p = LatticePolytope(m, compute_vertices=False, copy_vertices=False) sage: m.is_mutable() False sage: m is p.vertices() True
We draw a pretty picture of the polytype in 3-dimensional space:
sage: p.plot().show()
Now we add an extra point, which is in the interiour of the polytope...
sage: m = matrix(ZZ, [[1, 0, 0, -1, 0, 0, 0], ... [0, 1, 0, 0, -1, 0, 0], ... [0, 0, 1, 0, 0, -1, 0]]) ... sage: p = LatticePolytope(m, "A lattice polytope constructed from 7 points") sage: p A lattice polytope constructed from 7 points: 3-dimensional, 6 vertices.
You can suppress vertex computation for speed but this can lead to mistakes:
sage: p = LatticePolytope(m, "A lattice polytope with WRONG vertices", ... compute_vertices=False) ... sage: p A lattice polytope with WRONG vertices: 3-dimensional, 7 vertices.
Points of the given matrix must always span the space, this conditions will
be checked unless you specify compute_vertices=False
option:
sage: m = matrix(ZZ, [[1, 0, -1, 0], ... [0, 1, 0, -1], ... [0, 0, 0, 0]]) ... sage: p = LatticePolytope(m) Traceback (most recent call last): ... ValueError: Points must span the space! Given: [ 1 0 -1 0] [ 0 1 0 -1] [ 0 0 0 0]
dim, n) |
Return n-th reflexive polytope from the database of 2- or 3-dimensional reflexive polytopes.
NOTES: 1. Numeration starts with zero: 0<=n<=15 for dim=2 and 0<=n<=4318 for dim=3. 2. During the first call, all reflexive polytopes of requested dimension are loaded and cached for future use, so the first call for 3-dimensional polytopes can take several seconds, but all consecutive calls are fast. 3. Equivalent to ReflexivePolytopes(dim)[n] but checks bounds first.
The 3rd 2-dimensional polytope is "the diamond:"
sage: ReflexivePolytope(2,3) Reflexive polygon 3: 2-dimensional, 4 vertices. sage: lattice_polytope.ReflexivePolytope(2,3).vertices() [ 1 0 0 -1] [ 0 1 -1 0]
There are 16 reflexive polygons and numeration starts with 0:
sage: ReflexivePolytope(2,16) Traceback (most recent call last): ... ValueError: there are only 16 reflexive polygons!
It is not possible to load a 4-dimensional polytope in this way:
sage: ReflexivePolytope(4,16) Traceback (most recent call last): ... NotImplementedError: only 2- and 3-dimensional reflexive polytopes are available!
dim) |
Return the sequence of all 2- or 3-dimensional reflexive polytopes.
NOTE: During the first call the database is loaded and cached for future use, so repetitive calls will return the same object in memory.
TODO: load a database with precomputed faces. Requires better pickling, otherwise takes forever!
There are 16 reflexive polygons:
sage: len(ReflexivePolytopes(2)) 16
It is not possible to load 4-dimensional polytopes in this way:
sage: ReflexivePolytopes(4) Traceback (most recent call last): ... NotImplementedError: only 2- and 3-dimensional reflexive polytopes are available!
polytopes) |
Compute all cached data for all given polytopes
and their polars.
This functions does it MUCH faster than member functions of codeLatticePolytope during the first run. So it is recommended to use this functions if you work with big sets of data. None of the polytopes in the given sequence should be constructed as the polar polytope to another one.
Input: a sequence of lattice polytopes.
This function has no output, it is just a fast way to work with long sequences of polytopes. Of course, you can use short sequences as well:
sage: o = lattice_polytope.octahedron(3) sage: lattice_polytope.all_cached_data([o]) sage: o.faces() [ [[5], [1], [0], [3], [4], [2]], [[1, 5], [0, 5], [0, 1], [3, 5], [1, 3], [4, 5], [0, 4], [3, 4], [1, 2], [0, 2], [2, 3], [2, 4]], [[0, 1, 5], [1, 3, 5], [0, 4, 5], [3, 4, 5], [0, 1, 2], [1, 2, 3], [0, 2, 4], [2, 3, 4]] ]
However, you cannot use it for polytopes that are constructed as polar polytopes of others:
sage: lattice_polytope.all_cached_data([o.polar()]) Traceback (most recent call last): ... ValueError: Cannot read face structure for a polytope constructed as polar, use _compute_faces!
polytopes) |
Compute faces for all given polytopes
.
This functions does it MUCH faster than member functions of codeLatticePolytope during the first run. So it is recommended to use this functions if you work with big sets of data.
Input: a sequence of lattice polytopes.
This function has no output, it is just a fast way to work with long sequences of polytopes. Of course, you can use short sequences as well:
sage: o = lattice_polytope.octahedron(3) sage: lattice_polytope.all_faces([o]) sage: o.faces() [ [[5], [1], [0], [3], [4], [2]], [[1, 5], [0, 5], [0, 1], [3, 5], [1, 3], [4, 5], [0, 4], [3, 4], [1, 2], [0, 2], [2, 3], [2, 4]], [[0, 1, 5], [1, 3, 5], [0, 4, 5], [3, 4, 5], [0, 1, 2], [1, 2, 3], [0, 2, 4], [2, 3, 4]] ]
However, you cannot use it for polytopes that are constructed as polar polytopes of others:
sage: lattice_polytope.all_faces([o.polar()]) Traceback (most recent call last): ... ValueError: Cannot read face structure for a polytope constructed as polar, use _compute_faces!
polytopes, [keep_symmetric=False]) |
Compute NEF-partitions for all given polytopes
.
This functions does it MUCH faster than member functions of codeLatticePolytope during the first run. So it is recommended to use this functions if you work with big sets of data.
Note: member function is_reflexive
will be called separately for each
polytope. It is strictly recommended to call all_polars
on the
sequence of polytopes
before using this function.
Input: a sequence of lattice polytopes.
This function has no output, it is just a fast way to work with long sequences of polytopes. Of course, you can use short sequences as well:
sage: o = lattice_polytope.octahedron(3) sage: lattice_polytope.all_nef_partitions([o]) sage: o.nef_partitions() [ [1, 1, 0, 1, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 0, 0] ]
You cannot use this function for non-reflexive polytopes:
sage: m = matrix(ZZ, [[1, 0, 0, -1, 0, 0], ... [0, 1, 0, 0, -1, 0], ... [0, 0, 2, 0, 0, -1]]) ... sage: p = LatticePolytope(m) sage: lattice_polytope.all_nef_partitions([o, p]) Traceback (most recent call last): ... ValueError: The given polytope is not reflexive! Polytope: A lattice polytope: 3-dimensional, 6 vertices.
polytopes) |
Compute lattice points for all given polytopes
.
This functions does it MUCH faster than member functions of codeLatticePolytope during the first run. So it is recommended to use this functions if you work with big sets of data.
Input: a sequence of lattice polytopes.
This function has no output, it is just a fast way to work with long sequences of polytopes. Of course, you can use short sequences as well:
sage: o = lattice_polytope.octahedron(3) sage: lattice_polytope.all_points([o]) sage: o.points() [ 1 0 0 -1 0 0 0] [ 0 1 0 0 -1 0 0] [ 0 0 1 0 0 -1 0]
polytopes) |
Compute polar polytopes for all reflexive and equations of facets for all
non-reflexive polytopes
.
This functions does it MUCH faster than member functions of codeLatticePolytope during the first run. So it is recommended to use this functions if you work with big sets of data.
Input: a sequence of lattice polytopes.
This function has no output, it is just a fast way to work with long sequences of polytopes. Of course, you can use short sequences as well:
sage: o = lattice_polytope.octahedron(3) sage: lattice_polytope.all_polars([o]) sage: o.polar() A polytope polar to An octahedron: 3-dimensional, 8 vertices.
points) |
Compute the convex hull of the given points.
NOTE: points might not span the space. NOTE: fails for large numbers of vertices in dimensions 4 or greater
Input:
Let's compute the convex hull of several points on a line in the plane:
sage: lattice_polytope.convex_hull([[1,2],[3,4],[5,6],[7,8]]) [(1, 2), (7, 8)]
f, polytopes, [subseq=None], [print_numbers=False]) |
Use the function f
to filter polytopes in a list.
Input:
f
.
f
returns True)
and are elements of subseq, if it is given.
Consider a sequence of octahedrons:
sage: polytopes = Sequence([lattice_polytope.octahedron(n) for n in range(2, 7)], cr=True) sage: polytopes [ An octahedron: 2-dimensional, 4 vertices., An octahedron: 3-dimensional, 6 vertices., An octahedron: 4-dimensional, 8 vertices., An octahedron: 5-dimensional, 10 vertices., An octahedron: 6-dimensional, 12 vertices. ]
This filters octahedrons of dimension at least 4:
sage: lattice_polytope.filter_polytopes(lambda p: p.dim() >= 4, polytopes) [2, 3, 4]
For long tests you can see the current progress:
sage: lattice_polytope.filter_polytopes(lambda p: p.nvertices() >= 10, polytopes, print_numbers=True) 0 1 2 3 4 [3, 4]
Here we consider only some of the polytopes:
sage: lattice_polytope.filter_polytopes(lambda p: p.nvertices() >= 10, polytopes, [2, 3, 4], print_numbers=True) 2 3 4 [3, 4]
points1, points2) |
Compute the Minkowski sum of two convex polytopes.
NOTE: polytopes might not be of maximal dimension.
Input:
Let's compute the Minkovski sum of two line segments:
sage: lattice_polytope.minkowski_sum([[1,0],[-1,0]],[[0,1],[0,-1]]) [(1, 1), (1, -1), (-1, 1), (-1, -1)]
dim) |
Return an octahedron of the given dimension.
Here are 3- and 4-dimensional octahedrons:
sage: o = lattice_polytope.octahedron(3) sage: o An octahedron: 3-dimensional, 6 vertices. sage: o.vertices() [ 1 0 0 -1 0 0] [ 0 1 0 0 -1 0] [ 0 0 1 0 0 -1] sage: o = lattice_polytope.octahedron(4) sage: o An octahedron: 4-dimensional, 8 vertices. sage: o.vertices() [ 1 0 0 0 -1 0 0 0] [ 0 1 0 0 0 -1 0 0] [ 0 0 1 0 0 0 -1 0] [ 0 0 0 1 0 0 0 -1]
There exists only one octahedron of each dimension:
sage: o is lattice_polytope.octahedron(4) True
points) |
Return relations between given points.
Input:
This is a 3-dimensional reflexive polytope:
sage: m = matrix(ZZ,[[1, 0, -1, 0, -1], ... [0, 1, -1, 0, 0], ... [0, 0, 0, 1, -1]]) ... sage: p = LatticePolytope(m) sage: p.points() [ 1 0 -1 0 -1 0] [ 0 1 -1 0 0 0] [ 0 0 0 1 -1 0]
We can compute linear relations between its points in the following way:
sage: p.points().transpose().kernel().echelonized_basis_matrix() [ 1 0 0 1 1 0] [ 0 1 1 -1 -1 0] [ 0 0 0 0 0 1]
However, the above relations may contain negative and rational numbers. This function transforms them in such a way, that all coefficients are non-negative integers:
sage: lattice_polytope.positive_integer_relations(p.points()) [1 0 0 1 1 0] [1 1 1 0 0 0] [0 0 0 0 0 1]
dim) |
Return a simplex of the given dimension, corresponding to
.
We construct 3- and 4-dimensional simplexes:
sage: p = lattice_polytope.projective_space(3) sage: p A simplex: 3-dimensional, 4 vertices. sage: p.vertices() [ 1 0 0 -1] [ 0 1 0 -1] [ 0 0 1 -1] sage: p = lattice_polytope.projective_space(4) sage: p A simplex: 4-dimensional, 5 vertices. sage: p.vertices() [ 1 0 0 0 -1] [ 0 1 0 0 -1] [ 0 0 1 0 -1] [ 0 0 0 1 -1]
file_name, [desc=None]) |
Read all polytopes from the given file.
Input:
desc % n
where n
is the number of
the polytope in the file (STARTING WITH ZERO).
We use poly.x to compute polar polytopes of 2- and 3-octahedrons and read them:
sage: o2 = lattice_polytope.octahedron(2) sage: o3 = lattice_polytope.octahedron(3) sage: result_name = lattice_polytope._palp("poly.x -fe", [o2, o3]) sage: f = open(result_name) sage: f.readlines() ['4 2 Vertices of P-dual <-> Equations of P\n', ' -1 1\n', ' 1 1\n', ' -1 -1\n', ' 1 -1\n', '8 3 Vertices of P-dual <-> Equations of P\n', ' -1 -1 1\n', ' 1 -1 1\n', ' -1 1 1\n', ' 1 1 1\n', ' -1 -1 -1\n', ' 1 -1 -1\n', ' -1 1 -1\n', ' 1 1 -1\n'] sage: f.close() sage: lattice_polytope.read_all_polytopes(result_name, desc="Polytope from file %d") [ Polytope from file 0: 2-dimensional, 4 vertices., Polytope from file 1: 3-dimensional, 8 vertices. ] sage: os.remove(result_name)
data) |
Read and return an integer matrix from a string or an opened file.
First input line must start with two integers m and n, the number of rows and columns of the matrix. The rest of the first line is ignored. The next m lines must contain n numbers each.
If m>n, returns the transposed matrix.
If the string is empty or EOF is reached, returns the empty matrix,
constructed by matrix()
.
sage: lattice_polytope.read_palp_matrix("2 3 comment \n 1 2 3 \n 4 5 6") [1 2 3] [4 5 6] sage: lattice_polytope.read_palp_matrix("3 2 Will be transposed \n 1 2 \n 3 4 \n 5 6") [1 3 5] [2 4 6]
m) |
Convert a SAGE matrix to the string representation of Maxima.
sage: m = matrix(ZZ,2) sage: lattice_polytope.sage_matrix_to_maxima(m) matrix([0,0],[0,0])
data, [n=1]) |
Skip matrix data in a file.
Input:
If EOF is reached during the process, raises ValueError exception.
We create a file with vertices of the square and the cube, but read only the second set:
sage: o2 = lattice_polytope.octahedron(2) sage: o3 = lattice_polytope.octahedron(3) sage: result_name = lattice_polytope._palp("poly.x -fe", [o2, o3]) sage: f = open(result_name) sage: f.readlines() ['4 2 Vertices of P-dual <-> Equations of P\n', ' -1 1\n', ' 1 1\n', ' -1 -1\n', ' 1 -1\n', '8 3 Vertices of P-dual <-> Equations of P\n', ' -1 -1 1\n', ' 1 -1 1\n', ' -1 1 1\n', ' 1 1 1\n', ' -1 -1 -1\n', ' 1 -1 -1\n', ' -1 1 -1\n', ' 1 1 -1\n'] sage: f.close() sage: f = open(result_name) sage: lattice_polytope.skip_palp_matrix(f) sage: lattice_polytope.read_palp_matrix(f) [-1 1 -1 1 -1 1 -1 1] [-1 -1 1 1 -1 -1 1 1] [ 1 1 1 1 -1 -1 -1 -1] sage: f.close() sage: os.remove(result_name)
m, [ofile=None], [comment=], [format=None]) |
Write a matrix into a file.
Input:
This functions is used for writing polytope vertices in PALP format:
sage: o = lattice_polytope.octahedron(3) sage: lattice_polytope.write_palp_matrix(o.vertices(), comment="3D Octahedron") 3 6 3D Octahedron 1 0 0 -1 0 0 0 1 0 0 -1 0 0 0 1 0 0 -1 sage: lattice_polytope.write_palp_matrix(o.vertices(), format="%4d") 3 6 1 0 0 -1 0 0 0 1 0 0 -1 0 0 0 1 0 0 -1
Class: _PolytopeFace
Construct a polytope face.
POLYTOPE FACES SHOULD NOT BE CONSTRUCTED OUTSIDE OF LATTICE POLYTOPES!
Input:
self, polytope, vertices, facets) |
Construct a face.
TESTS:
sage: o = lattice_polytope.octahedron(2) sage: o.faces() [ [[3], [0], [2], [1]], [[0, 3], [2, 3], [0, 1], [1, 2]] ]
Functions: boundary_points,
facets,
interior_points,
nboundary_points,
nfacets,
ninterior_points,
npoints,
nvertices,
ordered_points,
points,
traverse_boundary,
vertices
self) |
Return a sequence of indices of boundary lattice points of this face.
Boundary lattice points of one of the facets of the 3-dimensional cube:
sage: o = lattice_polytope.octahedron(3) sage: cube = o.polar() sage: face = cube.facets()[0] sage: face.boundary_points() [0, 1, 2, 3, 11, 15, 21, 25]
self) |
Return a sequence of indices of facets containing this face.
Facets containing one of the edges of the 3-dimensional octahedron:
sage: o = lattice_polytope.octahedron(3) sage: edge = o.faces(dim=1)[0] sage: edge.facets() [0, 1]
Thus edge
is the intersection of facets 0 and 1:
sage: edge [1, 5] sage: o.facets()[0] [0, 1, 5] sage: o.facets()[1] [1, 3, 5]
self) |
Return a sequence of indices of interior lattice points of this face.
Interior lattice points of one of the facets of the 3-dimensional cube:
sage: o = lattice_polytope.octahedron(3) sage: cube = o.polar() sage: face = cube.facets()[0] sage: face.interior_points() [18]
self) |
Return the number of boundary lattice points of this face.
The number of boundary lattice points of one of the facets of the 3-dimensional cube:
sage: o = lattice_polytope.octahedron(3) sage: cube = o.polar() sage: face = cube.facets()[0] sage: face.nboundary_points() 8
self) |
Return the number of facets containing this face.
The number of facets containing one of the edges of the 3-dimensional octahedron:
sage: o = lattice_polytope.octahedron(3) sage: edge = o.faces(dim=1)[0] sage: edge.nfacets() 2
self) |
Return the number of interior lattice points of this face.
The number of interior lattice points of one of the facets of the 3-dimensional cube:
sage: o = lattice_polytope.octahedron(3) sage: cube = o.polar() sage: face = cube.facets()[0] sage: face.ninterior_points() 1
self) |
Return the number of lattice points of this face.
The number of lattice points of one of the facets of the 3-dimensional cube:
sage: o = lattice_polytope.octahedron(3) sage: cube = o.polar() sage: face = cube.facets()[0] sage: face.npoints() 9
self) |
Return the number of vertices generating this face.
The number of vertices generating one of the facets of the 3-dimensional cube:
sage: o = lattice_polytope.octahedron(3) sage: cube = o.polar() sage: face = cube.facets()[0] sage: face.nvertices() 4
self) |
Return the list of indices of lattice points on the edge in their geometric order, from one vertex to other.
Works only for edges, i.e. faces generated by exactly two vertices.
We find all points along an edge of the cube:
sage: o = lattice_polytope.octahedron(3) sage: c = o.polar() sage: e = c.edges()[0] sage: e.vertices() [0, 1] sage: e.ordered_points() [0, 15, 1]
self) |
Return a sequence of indices of lattice points of this face.
The lattice points of one of the facets of the 3-dimensional cube:
sage: o = lattice_polytope.octahedron(3) sage: cube = o.polar() sage: face = cube.facets()[0] sage: face.points() [0, 1, 2, 3, 11, 15, 18, 21, 25]
self) |
Return a list of indices of vertices of a 2-face in their boundary order.
Needed for plot3d function of polytopes.
sage: c = lattice_polytope.octahedron(3).polar() sage: f = c.facets()[0] sage: f.vertices() [0, 1, 2, 3] sage: f.traverse_boundary() [0, 2, 3, 1]
self) |
Return a sequence of indices of vertices generating this face.
The vertices generating one of the facets of the 3-dimensional cube:
sage: o = lattice_polytope.octahedron(3) sage: cube = o.polar() sage: face = cube.facets()[0] sage: face.vertices() [0, 1, 2, 3]
Special Functions: __init__,
__reduce__,
_repr_
self) |
Reduction function. Does not store data that can be relatively fast recomputed.
TESTS:
sage: o = lattice_polytope.octahedron(2) sage: f = o.facets()[0] sage: fl = loads(f.dumps()) sage: f.vertices() == fl.vertices() True sage: f.facets() == fl.facets() True
self) |
Return a string representation of this face.
TESTS:
sage: o = lattice_polytope.octahedron(3) sage: f = o.facets()[0] sage: f._repr_() '[0, 1, 5]'
Class: LatticePolytopeClass
Use LatticePolytope
for constructing a polytope.
self, data, desc, compute_vertices, [copy_vertices=True], [n=0]) |
Construct a lattice polytope. See LatticePolytope
.
Most tests/examples are also done in LatticePolytope.
TESTS:
sage: LatticePolytope(matrix(ZZ,[[1,2,3],[4,5,6]])) Traceback (most recent call last): ... ValueError: Points must span the space! Given: [1 2 3] [4 5 6]
Functions: dim,
distances,
edges,
faces,
facets,
index,
is_reflexive,
mif,
nef_partitions,
nef_x,
nfacets,
normal_form,
npoints,
nvertices,
parent,
plot,
plot3d,
point,
points,
polar,
poly_x,
show,
skeleton,
skeleton_points,
skeleton_show,
vertex,
vertices
self) |
Return the dimension of this polytope.
We create a 3-dimensional octahedron and check its dimension:
sage: o = lattice_polytope.octahedron(3) sage: o.dim() 3
self, [point=None]) |
Return the matrix of distances for this polytope or distances for the given point.
The matrix of distances m gives distances m[i,j] between the i-th facet (which is also the i-th vertex of the polar polytope in the reflexive case) and j-th point of this polytope.
If point is specified, integral distances from the point to all facets of this polytope will be computed.
The matrix of distances for a 3-dimensional octahedron:
sage: o = lattice_polytope.octahedron(3) sage: o.distances() [0 0 2 2 2 0 1] [2 0 2 0 2 0 1] [0 2 2 2 0 0 1] [2 2 2 0 0 0 1] [0 0 0 2 2 2 1] [2 0 0 0 2 2 1] [0 2 0 2 0 2 1] [2 2 0 0 0 2 1]
Distances from facets to the point (1,2,3):
sage: o.distances([1,2,3]) (1, 3, 5, 7, -5, -3, -1, 1)
It is OK to use RATIONAL coordinates:
sage: o.distances([1,2,3/2]) (-1/2, 3/2, 7/2, 11/2, -7/2, -3/2, 1/2, 5/2) sage: o.distances([1,2,sqrt(2)]) Traceback (most recent call last): ... TypeError: unable to convert sqrt(2) to a rational
self) |
Return the sequence of edges of this polytope (i.e. faces of dimension 1).
The octahedron has 12 edges:
sage: o = lattice_polytope.octahedron(3) sage: len(o.edges()) 12 sage: o.edges() [[1, 5], [0, 5], [0, 1], [3, 5], [1, 3], [4, 5], [0, 4], [3, 4], [1, 2], [0, 2], [2, 3], [2, 4]]
self, [dim=None], [codim=None]) |
Return the sequence of faces of this polytope.
If dim
or codim
are specified, returns a sequence of
faces of the corresponding dimension or codimension. Otherwise returns
the sequence of such sequences for all dimensions.
All faces of the 3-dimensional octahedron:
sage: o = lattice_polytope.octahedron(3) sage: o.faces() [ [[5], [1], [0], [3], [4], [2]], [[1, 5], [0, 5], [0, 1], [3, 5], [1, 3], [4, 5], [0, 4], [3, 4], [1, 2], [0, 2], [2, 3], [2, 4]], [[0, 1, 5], [1, 3, 5], [0, 4, 5], [3, 4, 5], [0, 1, 2], [1, 2, 3], [0, 2, 4], [2, 3, 4]] ]
Its faces of dimension one (i.e., edges):
sage: o.faces(dim=1) [[1, 5], [0, 5], [0, 1], [3, 5], [1, 3], [4, 5], [0, 4], [3, 4], [1, 2], [0, 2], [2, 3], [2, 4]]
Its faces of codimension two (also edges):
sage: o.faces(codim=2) [[1, 5], [0, 5], [0, 1], [3, 5], [1, 3], [4, 5], [0, 4], [3, 4], [1, 2], [0, 2], [2, 3], [2, 4]]
It is an error to specify both dimension and codimension at the same time, even if they do agree:
sage: o.faces(dim=1, codim=2) Traceback (most recent call last): ... ValueError: Both dim and codim are given!
self) |
Return the sequence of facets of this polytope (i.e. faces of codimension 1).
All facets of the 3-dimensional octahedron:
sage: o = lattice_polytope.octahedron(3) sage: o.facets() [[0, 1, 5], [1, 3, 5], [0, 4, 5], [3, 4, 5], [0, 1, 2], [1, 2, 3], [0, 2, 4], [2, 3, 4]]
Facets are the same as faces of codimension one:
sage: o.facets() is o.faces(codim=1) True
self) |
Return the index of this polytope in the internal database of 2- or 3-dimensional reflexive polytopes. Databases are stored in the directory of the package.
NOTE: The first call to this function for each dimension can take a second or so while the dictionary of all polytopes is loaded, but after that it is cached and fast.
We check what is the index of the "diamond" in the database:
sage: o = lattice_polytope.octahedron(2) sage: o.index() 3
Note that polytopes with the same index are not necessarily the same:
sage: o.vertices() [ 1 0 -1 0] [ 0 1 0 -1] sage: lattice_polytope.ReflexivePolytope(2,3).vertices() [ 1 0 0 -1] [ 0 1 -1 0]
But they are in the same
orbit and have the same normal form:
sage: o.normal_form() [ 1 0 0 -1] [ 0 1 -1 0] sage: lattice_polytope.ReflexivePolytope(2,3).normal_form() [ 1 0 0 -1] [ 0 1 -1 0]
self) |
Return True if this polytope is reflexive.
The 3-dimensional octahedron is reflexive (and 4318 other 3-polytopes):
sage: o = lattice_polytope.octahedron(3) sage: o.is_reflexive() True
But not all polytopes are reflexive:
sage: m = matrix(ZZ, [[1, 0, 0, -1, 0, 0], ... [0, 1, 0, 0, -1, 0], ... [0, 0, 0, 0, 0, -1]]) ... sage: p = LatticePolytope(m) sage: p.is_reflexive() False
self, partition) |
Return all vectors
, grouped into matrices.
Input:
We compute
matrices for one of the nef-partitions of
the 3-dimensional octahedron:
sage: o = lattice_polytope.octahedron(3) sage: nefp = o.nef_partitions()[0] sage: o.mif(nefp) [ [ 0 0 1] [-1 -1 0], [ 0 0 1] [ 1 -1 0], [ 0 1 1] [-1 0 0], [0 1 1] [1 0 0], [ 0 0 -1] [-1 -1 0], [ 0 0 -1] [ 1 -1 0], [ 0 1 -1] [-1 0 0], [ 0 1 -1] [ 1 0 0] ]
self, [keep_symmetric=False], [keep_products=True], [keep_projections=True], [hodge_numbers=False]) |
Return the sequence of NEF-partitions for this polytope.
Input:
NEF-partitions of the 4-dimensional octahedron:
sage: o = lattice_polytope.octahedron(4) sage: o.nef_partitions() [ [1, 1, 0, 0, 1, 1, 0, 0] (direct product), [1, 1, 1, 0, 1, 0, 0, 0], [1, 1, 1, 0, 1, 1, 0, 0], [1, 1, 1, 0, 1, 1, 1, 0] (direct product), [1, 1, 1, 1, 0, 0, 0, 0], [1, 1, 1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 1, 1, 0, 0], [1, 1, 1, 1, 1, 1, 1, 0] (projection) ]
Now we omit projections:
sage: o.nef_partitions(keep_projections=False) [ [1, 1, 0, 0, 1, 1, 0, 0] (direct product), [1, 1, 1, 0, 1, 0, 0, 0], [1, 1, 1, 0, 1, 1, 0, 0], [1, 1, 1, 0, 1, 1, 1, 0] (direct product), [1, 1, 1, 1, 0, 0, 0, 0], [1, 1, 1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 1, 1, 0, 0] ]
At present, Hodge numbers cannot be computed for a given NEF-partition:
sage: o.nef_partitions()[1].hodge_numbers() Traceback (most recent call last): ... NotImplementedError: use nef_partitions(hodge_numbers=True)!
But they can be obtained from nef.x for all partitions at once. Partitions will be exactly the same:
sage: o.nef_partitions(hodge_numbers=True) [ [1, 1, 0, 0, 1, 1, 0, 0] (direct product), [1, 1, 1, 0, 1, 0, 0, 0], [1, 1, 1, 0, 1, 1, 0, 0], [1, 1, 1, 0, 1, 1, 1, 0] (direct product), [1, 1, 1, 1, 0, 0, 0, 0], [1, 1, 1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 1, 1, 0, 0], [1, 1, 1, 1, 1, 1, 1, 0] (projection) ]
Now it is possible to get Hodge numbers:
sage: o.nef_partitions(hodge_numbers=True)[1].hodge_numbers() [20]
Since NEF-partitions are cached, Hodge numbers are accessible after the first request, even if you do not specify hodge_numbers anymore:
sage: o.nef_partitions()[1].hodge_numbers() [20]
We illustrate removal of symmetric partitions on a diamond:
sage: o = lattice_polytope.octahedron(2) sage: o.nef_partitions() [ [1, 0, 1, 0] (direct product), [1, 1, 0, 0], [1, 1, 1, 0] (projection) ] sage: o.nef_partitions(keep_symmetric=True) [ [1, 1, 0, 1] (projection), [1, 0, 1, 1] (projection), [1, 0, 0, 1], [0, 1, 1, 1] (projection), [0, 1, 0, 1] (direct product), [0, 0, 1, 1], [1, 1, 1, 0] (projection) ]
NEF-partitions can be computed only for reflexive polytopes:
sage: m = matrix(ZZ, [[1, 0, 0, -1, 0, 0], ... [0, 1, 0, 0, -1, 0], ... [0, 0, 2, 0, 0, -1]]) ... sage: p = LatticePolytope(m) sage: p.nef_partitions() Traceback (most recent call last): ... ValueError: The given polytope is not reflexive! Polytope: A lattice polytope: 3-dimensional, 6 vertices.
self, keys) |
Run nef.x wilth given keys
on vertices of this polytope.
Input:
This call is used internally for computing NEF-partitions:
sage: o = lattice_polytope.octahedron(3) sage: s = o.nef_x("-N -V -p") sage: s # output contains random time M:27 8 N:7 6 codim=2 #part=5 3 6 Vertices of P: 1 0 0 -1 0 0 0 1 0 0 -1 0 0 0 1 0 0 -1 P:0 V:2 4 5 0sec 0cpu P:2 V:3 4 5 0sec 0cpu P:3 V:4 5 0sec 0cpu np=3 d:1 p:1 0sec 0cpu
self) |
Return the number of facets of this polytope.
The number of facets of the 3-dimensional octahedron:
sage: o = lattice_polytope.octahedron(3) sage: o.nfacets() 8
self) |
Two lattice polytopes are in the same GL(Z)-orbit if and only if their normal forms are the same.
We compute the normal form of the "diamond":
sage: o = lattice_polytope.octahedron(2) sage: o.vertices() [ 1 0 -1 0] [ 0 1 0 -1] sage: o.normal_form() [ 1 0 0 -1] [ 0 1 -1 0]
The diamond is the 3rd polytope in the internal database...
sage: o.index() 3 sage: lattice_polytope.ReflexivePolytope(2,3).vertices() [ 1 0 0 -1] [ 0 1 -1 0]
self) |
Return the number of lattice points of this polytope.
The number of lattice points of the 3-dimensional octahedron and its polar cube:
sage: o = lattice_polytope.octahedron(3) sage: o.npoints() 7 sage: cube = o.polar() sage: cube.npoints() 27
self) |
Return the number of vertices of this polytope.
The number of vertices of the 3-dimensional octahedron and its polar cube:
sage: o = lattice_polytope.octahedron(3) sage: o.nvertices() 6 sage: cube = o.polar() sage: cube.nvertices() 8
self) |
Return the set of all lattice polytopes.
sage: o = lattice_polytope.octahedron(3) sage: o.parent() Set of all Lattice Polytopes
self, [camera_center=None]) |
Draw a 3d picture of the polytope.
Input:
The face colors are random.
Author: William Stein and Tom Boothby
sage: o = lattice_polytope.octahedron(3) sage: o.plot().show()
self, [show_facets=True], [facet_opacity=0.5], [facet_color=(0, 1, 0)], [show_edges=True], [edge_thickness=3], [edge_color=(0.5, 0.5, 0.5)], [show_vertices=True], [vertex_size=10], [vertex_color=(1, 0, 0)], [show_points=True], [point_size=10], [point_color=(0, 0, 1)], [show_vindices=None], [vindex_color=(0, 0, 0)], [show_pindices=None], [pindex_color=(0, 0, 0)], [index_shift=1.1]) |
Return a 3d-plot of a 3-dimensional polytope.
By default, everything is shown with more or less pretty combination of size and color parameters.
Input: Most of the parameters are self-explanatory:
The default plot of a cube:
sage: c = lattice_polytope.octahedron(3).polar() sage: c.plot3d()
Plot without facets and points, shown without the frame:
sage: c.plot3d(show_facets=false,show_points=false).show(frame=False)
TESTS:
sage: m = matrix([[0,0,0],[0,1,1],[1,0,1],[1,1,0]]).transpose() sage: p = LatticePolytope(m, compute_vertices=True) sage: p.plot3d()
self, i) |
Return the i-th point of this polytope, i.e. the i-th column of the matrix returned by points().
First few points are actually vertices:
sage: o = lattice_polytope.octahedron(3) sage: o.vertices() [ 1 0 0 -1 0 0] [ 0 1 0 0 -1 0] [ 0 0 1 0 0 -1] sage: o.point(1) (0, 1, 0)
The only other point in the octahedron is the origin:
sage: o.point(6) (0, 0, 0) sage: o.points() [ 1 0 0 -1 0 0 0] [ 0 1 0 0 -1 0 0] [ 0 0 1 0 0 -1 0]
self) |
Return all lattice points of this polytope as columns of a matrix.
The lattice points of the 3-dimensional octahedron and its polar cube:
sage: o = lattice_polytope.octahedron(3) sage: o.points() [ 1 0 0 -1 0 0 0] [ 0 1 0 0 -1 0 0] [ 0 0 1 0 0 -1 0] sage: cube = o.polar() sage: cube.points() [-1 1 -1 1 -1 1 -1 1 -1 -1 -1 -1 -1 0 0 0 0 0 0 0 0 0 1 1 1 1 1] [-1 -1 1 1 -1 -1 1 1 -1 0 0 0 1 -1 -1 -1 0 0 0 1 1 1 -1 0 0 0 1] [ 1 1 1 1 -1 -1 -1 -1 0 -1 0 1 0 -1 0 1 -1 0 1 -1 0 1 0 -1 0 1 0]
self) |
Return the polar polytope, if this polytope is reflexive.
The polar polytope to the 3-dimensional octahedron:
sage: o = lattice_polytope.octahedron(3) sage: cube = o.polar() sage: cube A polytope polar to An octahedron: 3-dimensional, 8 vertices.
The polar polytope "remembers" the original one:
sage: cube.polar() An octahedron: 3-dimensional, 6 vertices. sage: cube.polar().polar() is cube True
Only reflexive polytopes have polars:
sage: m = matrix(ZZ, [[1, 0, 0, -1, 0, 0], ... [0, 1, 0, 0, -1, 0], ... [0, 0, 2, 0, 0, -1]]) ... sage: p = LatticePolytope(m) sage: p.polar() Traceback (most recent call last): ... ValueError: The given polytope is not reflexive! Polytope: A lattice polytope: 3-dimensional, 6 vertices.
self, keys) |
Run poly.x with given keys
on vertices of this polytope.
Input:
This call is used for determining if a polytope is reflexive or not:
sage: o = lattice_polytope.octahedron(3) sage: print o.poly_x("e") 8 3 Vertices of P-dual <-> Equations of P -1 -1 1 1 -1 1 -1 1 1 1 1 1 -1 -1 -1 1 -1 -1 -1 1 -1 1 1 -1
Since PALP has limits on different parameters determined during compilation, the following code is likely to fail, unless you change default settings of PALP:
sage: BIGO = lattice_polytope.octahedron(7) sage: BIGO An octahedron: 7-dimensional, 14 vertices. sage: BIGO.poly_x("e") # possibly different output depending on your system Traceback (most recent call last): ... ValueError: Error executing "poly.x -fe" for the given polytope! Polytope: An octahedron: 7-dimensional, 14 vertices. Vertices: [ 1 0 0 0 0 0 0 -1 0 0 0 0 0 0] [ 0 1 0 0 0 0 0 0 -1 0 0 0 0 0] [ 0 0 1 0 0 0 0 0 0 -1 0 0 0 0] [ 0 0 0 1 0 0 0 0 0 0 -1 0 0 0] [ 0 0 0 0 1 0 0 0 0 0 0 -1 0 0] [ 0 0 0 0 0 1 0 0 0 0 0 0 -1 0] [ 0 0 0 0 0 0 1 0 0 0 0 0 0 -1] Output: increase POLY_Dmax!
self, [camera_center=None]) |
Draw a 3d picture of the polytope.
See self.plot? for more details.
sage: o = lattice_polytope.octahedron(3) sage: o.show()
self) |
Return the graph of the one-skeleton of this polytope.
We construct the one-skeleton graph for the "diamond":
sage: o = lattice_polytope.octahedron(2) sage: g = o.skeleton() sage: g Graph on 4 vertices sage: g.edges() [(0, 1, None), (0, 3, None), (1, 2, None), (2, 3, None)]
self, [k=1]) |
Return the increasing list of indices of lattice points in k-skeleton of the polytope (k is 1 by default).
We compute all skeleton points for the cube:
sage: o = lattice_polytope.octahedron(3) sage: c = o.polar() sage: c.skeleton_points() [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 19, 21, 22, 23, 25, 26]
The default was 1-skeleton:
sage: c.skeleton_points(k=1) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 19, 21, 22, 23, 25, 26]
0-skeleton just lists all vertices:
sage: c.skeleton_points(k=0) [0, 1, 2, 3, 4, 5, 6, 7]
2-skeleton lists all points except for the origin (point #17):
sage: c.skeleton_points(k=2) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26]
3-skeleton includes all points:
sage: c.skeleton_points(k=3) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
It is OK to compute higher dimensional skeletons - you will get the list of all points:
sage: c.skeleton_points(k=100) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26]
self, [normal=None]) |
Works only for 3-dimensional polytopes.
Input:
Show a pretty picture of the octahedron:
sage: o = lattice_polytope.octahedron(3) sage: o.skeleton_show([1,2,4])
self, i) |
Return the i-th vertex of this polytope, i.e. the i-th column of the matrix returned by vertices().
Note that numeration starts with zero:
sage: o = lattice_polytope.octahedron(3) sage: o.vertices() [ 1 0 0 -1 0 0] [ 0 1 0 0 -1 0] [ 0 0 1 0 0 -1] sage: o.vertex(3) (-1, 0, 0)
self) |
Return vertices of this polytope as columns of a matrix.
The lattice points of the 3-dimensional octahedron and its polar cube:
sage: o = lattice_polytope.octahedron(3) sage: o.vertices() [ 1 0 0 -1 0 0] [ 0 1 0 0 -1 0] [ 0 0 1 0 0 -1] sage: cube = o.polar() sage: cube.vertices() [-1 1 -1 1 -1 1 -1 1] [-1 -1 1 1 -1 -1 1 1] [ 1 1 1 1 -1 -1 -1 -1]
Special Functions: __init__,
__reduce__,
__setstate__,
_compute_faces,
_compute_hodge_numbers,
_face_compute_points,
_face_split_points,
_palp,
_read_equations,
_read_faces,
_read_nef_partitions,
_repr_
self) |
Reduction function. Does not store data that can be relatively fast recomputed.
TESTS:
sage: o = lattice_polytope.octahedron(3) sage: o.vertices() == loads(o.dumps()).vertices() True
self, state) |
Restores the state of pickled polytope.
TESTS:
sage: o = lattice_polytope.octahedron(3) sage: o.vertices() == loads(o.dumps()).vertices() True
self) |
Compute and cache faces of this polytope.
If this polytope is reflexive and the polar polytope was already computed, computes faces of both in order to save time and preserve the one-to-one correspondence between the faces of this polytope of dimension d and the faces of the polar polytope of codimension d+1.
TESTS:
sage: o = lattice_polytope.octahedron(3) sage: v = o.__dict__.pop("_faces", None) # faces may be cached already sage: o.__dict__.has_key("_faces") False sage: o._compute_faces() sage: o.__dict__.has_key("_faces") True
self) |
Compute Hodge numbers for the current nef_partitions.
This function (currently) always raises an exception directing to use another way for computing Hodge numbers.
TESTS:
sage: o = lattice_polytope.octahedron(3) sage: o._compute_hodge_numbers() Traceback (most recent call last): ... NotImplementedError: use nef_partitions(hodge_numbers=True)!
self, face) |
Compute and cache lattice points of the given face
of this polytope.
TESTS:
sage: o = lattice_polytope.octahedron(3) sage: e = o.faces(dim=1)[0] sage: v = e.__dict__.pop("_points", None) # points may be cached already sage: e.__dict__.has_key("_points") False sage: o._face_compute_points(e) sage: e.__dict__.has_key("_points") True
self, face) |
Compute and cache boundary and interior lattice points of face
.
TESTS:
sage: c = lattice_polytope.octahedron(3).polar() sage: f = c.facets()[0] sage: v = f.__dict__.pop("_interior_points", None) sage: f.__dict__.has_key("_interior_points") False sage: v = f.__dict__.pop("_boundary_points", None) sage: f.__dict__.has_key("_boundary_points") False sage: c._face_split_points(f) sage: f._interior_points [18] sage: f._boundary_points [0, 1, 2, 3, 11, 15, 21, 25] sage: f.points() [0, 1, 2, 3, 11, 15, 18, 21, 25]
self, command) |
Run command
on vertices of this polytope.
Returns the output of command
as a string.
TESTS:
sage: o = lattice_polytope.octahedron(3) sage: o._palp("poly.x -f") 'M:7 6 N:27 8 Pic:17 Cor:0\n' sage: print o._palp("nef.x -f -N -p") # random time information M:27 8 N:7 6 codim=2 #part=5 H:[0] P:0 V:2 4 5 0sec 0cpu H:[0] P:2 V:3 4 5 0sec 0cpu H:[0] P:3 V:4 5 0sec 0cpu np=3 d:1 p:1 0sec 0cpu
self, data) |
Read equations of facets/vertices of polar polytope from string or file.
TESTS: For a reflexive polytope construct the polar polytope:
sage: p = LatticePolytope(matrix(ZZ,2,3,[1,0,-1,0,1,-1])) sage: p.vertices() [ 1 0 -1] [ 0 1 -1] sage: s = p.poly_x("e") sage: print s 3 2 Vertices of P-dual <-> Equations of P 2 -1 -1 2 -1 -1 sage: p.__dict__.has_key("_polar") False sage: p._read_equations(s) sage: p._polar._vertices [ 2 -1 -1] [-1 2 -1]
For a non-reflexive polytope cache facet equations:
sage: p = LatticePolytope(matrix(ZZ,2,3,[1,0,-1,0,2,-3])) sage: p.vertices() [ 1 0 -1] [ 0 2 -3] sage: p.__dict__.has_key("_facet_normals") False sage: p.__dict__.has_key("_facet_constants") False sage: s = p.poly_x("e") sage: print s 3 2 Equations of P 5 -1 2 -2 -1 2 -3 2 3 sage: p._read_equations(s) sage: p._facet_normals [ 5 -1] [-2 -1] [-3 2] sage: p._facet_constants (2, 2, 3)
self, data) |
Read faces informations from string or file.
TESTS:
sage: o = lattice_polytope.octahedron(3) sage: s = o.poly_x("i") sage: print s Incidences as binary numbers [F-vector=(6 12 8)]: v[d][i]: sum_j Incidence(i'th dim-d-face, j-th vertex) x 2^j v[0]: 100000 000010 000001 001000 010000 000100 v[1]: 100010 100001 000011 101000 001010 110000 010001 011000 000110 000101 001100 010100 v[2]: 100011 101010 110001 111000 000111 001110 010101 011100 f[d][i]: sum_j Incidence(i'th dim-d-face, j-th facet) x 2^j f[0]: 00001111 00110011 01010101 10101010 11001100 11110000 f[1]: 00000011 00000101 00010001 00001010 00100010 00001100 01000100 10001000 00110000 01010000 10100000 11000000 f[2]: 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000 sage: v = o.__dict__.pop("_faces", None) sage: o.__dict__.has_key("_faces") False sage: o._read_faces(s) sage: o._faces [ [[5], [1], [0], [3], [4], [2]], [[1, 5], [0, 5], [0, 1], [3, 5], [1, 3], [4, 5], [0, 4], [3, 4], [1, 2], [0, 2], [2, 3], [2, 4]], [[0, 1, 5], [1, 3, 5], [0, 4, 5], [3, 4, 5], [0, 1, 2], [1, 2, 3], [0, 2, 4], [2, 3, 4]] ]
Cannot be used for "polar polytopes," their faces are constructed from faces of the original one to preserve facial duality.
sage: c = o.polar() sage: s = c.poly_x("i") sage: print s Incidences as binary numbers [F-vector=(8 12 6)]: v[d][i]: sum_j Incidence(i'th dim-d-face, j-th vertex) x 2^j v[0]: 00010000 00000001 01000000 00000100 00100000 00000010 10000000 00001000 v[1]: 00010001 01010000 00000101 01000100 00110000 00000011 00100010 11000000 10100000 00001100 00001010 10001000 v[2]: 01010101 00110011 11110000 00001111 11001100 10101010 f[d][i]: sum_j Incidence(i'th dim-d-face, j-th facet) x 2^j f[0]: 000111 001011 010101 011001 100110 101010 110100 111000 f[1]: 000011 000101 001001 010001 000110 001010 100010 010100 100100 011000 101000 110000 f[2]: 000001 000010 000100 001000 010000 100000 sage: c._read_faces(s) Traceback (most recent call last): ... ValueError: Cannot read face structure for a polytope constructed as polar, use _compute_faces!
self, data) |
Read NEF-partitions from string or file.
TESTS:
sage: o = lattice_polytope.octahedron(3) sage: s = o.nef_x("-p -N -Lv") sage: print s # random time values M:27 8 N:7 6 codim=2 #part=5 3 6 Vertices in N-lattice: 1 0 0 -1 0 0 0 1 0 0 -1 0 0 0 1 0 0 -1 ------------------------------ 1 0 0 1 0 0 d=2 codim=2 0 1 0 0 1 0 d=2 codim=2 0 0 1 0 0 1 d=2 codim=2 P:0 V:2 4 5 (0 2) (1 1) (2 0) 0sec 0cpu P:2 V:3 4 5 (1 1) (1 1) (1 1) 0sec 0cpu P:3 V:4 5 (0 2) (1 1) (1 1) 0sec 0cpu np=3 d:1 p:1 0sec 0cpu sage: v = o.__dict__.pop("_nef_partitions", None) sage: o.__dict__.has_key("_nef_partitions") False sage: o._read_nef_partitions(s) sage: o._nef_partitions [ [1, 1, 0, 1, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 0, 0] ]
self) |
Return a string representation of this polytope.
TESTS:
sage: o = lattice_polytope.octahedron(3) sage: o._repr_() 'An octahedron: 3-dimensional, 6 vertices.'
Class: NEFPartition
A NEF-partition with
parts,
,
is represented by a single list of lenght
, in which the
-th
entry is the part number of the
-th vertex of a polytope.
NOTE THAT NUMERATON OF PARTS STARTS WITH ZERO.
All elements of the list will be coerced to integers, so it is OK to use either a list of numbers or a list of strings:
sage: lattice_polytope.NEFPartition([1, 1, 0, 0, 0, 1]) [1, 1, 0, 0, 0, 1] sage: lattice_polytope.NEFPartition(['1', '1', '0', '0', '0', '1']) [1, 1, 0, 0, 0, 1]
self, data, [polytope=None]) |
Construct a NEF-partition.
TESTS:
sage: lattice_polytope.NEFPartition([1,0,1,0]) [1, 0, 1, 0]
Functions: dual,
hodge_numbers,
nparts,
part,
part_of_vertex,
polytope
self) |
Compute dual nef-partition.
Computation follows the article "Combinatorial aspects of mirror symmetry" by V.Batyrev and B.Nill, initial polytope corresponds to Nabla*, output to Delta*.
We compute the dual nef-partition for the first nef-partition of the octahedron:
sage: o = lattice_polytope.octahedron(3) sage: np = o.nef_partitions()[0] sage: np [1, 1, 0, 1, 0, 0] sage: npd = np.dual() sage: npd [1, 0, 1, 0, 0, 1, 0, 1] sage: npd.polytope().vertices() [ 1 0 1 0 0 -1 0 -1] [-1 1 0 0 0 -1 1 0] [ 0 1 0 1 -1 0 -1 0]
self) |
Return Hodge numbers corresponding to the given nef-partition.
NOTE: In order to use this function you must use nef_partitions(hodge_numbers=True) for computing nef-partitions.
Currently, you need to request hodge_numbers when you compute nef-partitions. (The following weird construction ensures that there are no cached numbers.)
sage: o = LatticePolytope(lattice_polytope.octahedron(4).vertices()) sage: np = o.nef_partitions()[0] sage: np.hodge_numbers() Traceback (most recent call last): ... NotImplementedError: use nef_partitions(hodge_numbers=True)! sage: np = o.nef_partitions(hodge_numbers=True)[0] sage: np.hodge_numbers() [4]
self) |
Return the number of parts of this partitions.
sage: nefp = lattice_polytope.NEFPartition([1, 1, 0, 0, 0, 1]) sage: nefp.nparts() 2
self, i) |
Return the i
-th part of the partition.
NUMERATON OF PARTS STARTS WITH ZERO.
sage: nefp = lattice_polytope.NEFPartition([1, 1, 0, 0, 0, 1]) sage: nefp.part(0) [2, 3, 4] sage: nefp.part(1) [0, 1, 5]
self, i) |
Return the index of the part containing the i
-vertex.
nefp.part_of_vertex(i)
is equivalent to nefp[i]
.
sage: nefp = lattice_polytope.NEFPartition([1, 1, 0, 0, 0, 1]) sage: nefp.part_of_vertex(3) 0 sage: nefp.part_of_vertex(5) 1 sage: nefp[3] 0 sage: nefp[5] 1
You cannot change a NEF-partition once it is constructed:
sage: nefp[3] = 1 Traceback (most recent call last): ... ValueError: object is immutable; please change a copy instead.
self) |
Return the polytope of this NEF-partition.
sage: o = lattice_polytope.octahedron(3) sage: np = o.nef_partitions()[0] sage: np.polytope() == o True
Special Functions: __init__,
__reduce__,
_repr_
self) |
Reduction function. Does not store data that can be relatively fast recomputed.
TESTS:
sage: o = lattice_polytope.octahedron(3) sage: np = o.nef_partitions()[0] sage: np == loads(np.dumps()) True
self) |
Return a string representation of this NEF-partition.
TESTS:
sage: np = lattice_polytope.NEFPartition([1,1,0,0]) sage: np._repr_() '[1, 1, 0, 0]'
Class: SetOfAllLatticePolytopesClass
Special Functions: __call__,
_repr_
self, x) |
TESTS:
sage: o = lattice_polytope.octahedron(3) sage: lattice_polytope.SetOfAllLatticePolytopesClass().__call__(o) An octahedron: 3-dimensional, 6 vertices.
self) |
Return a string representation.
TESTS:
sage: lattice_polytope.SetOfAllLatticePolytopesClass()._repr_() 'Set of all Lattice Polytopes'
See About this document... for information on suggesting changes.