When used inside Sage, SnapPy can verify the following computations:
Complex intervals for the shapes that are guaranteed to contain a true solution to the rectangular gluing equations:
sage: M = Manifold("m015(3,1)") sage: M.tetrahedra_shapes('rect', intervals=True) [0.625222762246? + 3.177940133813?*I, -0.0075523593782? + 0.5131157955971?*I, 0.6515818912107? - 0.1955023488930?*I]
dec_precfor higher precision intervals.)
Verify the hyperbolicity of an orientable 3-manifold using intervals:
sage: M = Manifold("m015") sage: M.verify_hyperbolicity() (True, [0.6623589786224? + 0.5622795120623?*I, 0.6623589786224? + 0.5622795120623?*I, 0.6623589786224? + 0.5622795120623?*I])
Give the canonical retriangulation (a close relative to the canonical cell decomposition) of a cusped hyperbolic manifold using intervals or exact arithmetic if necessary:
sage: M = Manifold("m412") sage: K = M.canonical_retriangulation(M, verified = True) sage: len(K.isomorphisms_to(K)) # Certified size of isometry group 8
Remark: For the case of non-tetrahedral canonical cell, exact values are used which are found using the LLL-algorithm and then verified using exact computations. These computations can be slow. A massive speed-up was achieved by recent improvements so that the computation of the isometry signature of any manifold in
OrientableCuspedCensustakes at most a couple of seconds, typically, far less. Manifolds with more simplices might require setting a higher value for
The isometry signature which is a complete invariant of the isometry type of a cusped hyperbolic manifold (i.e., two manifolds are isometric if and only if they have the same isometry signature):
sage: M = Manifold("m412") sage: M.isometry_signature(verified = True) 'mvvLALQQQhfghjjlilkjklaaaaaffffffff'
The isometry signature can be strengthened to include the peripheral curves such that it is a complete invariant of a hyperbolic link:
sage: M = Manifold("L5a1") sage: M.isometry_signature(of_link = True, verified = True) 'eLPkbdcddhgggb_baCbbaCb'
Remark: The isometry signature is based on the canonical retriangulation so the same warning applies.
Complex intervals for the translations of meridian and longitude with respect to disjoint cusp neighborhoods:
sage: M = Manifold("s441") sage: M.cusp_translations("s441") [(0.30456698? + 1.38179990?*I, 1.84652839?), (0.30456698? + 1.38179990?*I, 1.84652839?)]
This is all based on a reimplementation of HIKMOT which pioneered the use of interval methods for hyperbolic manifolds. It can be used in a way very similar to HIKMOT, but uses Sage’s complex interval types and the Newton interval method (instead of the Krawczyk test) for certification. See Zgliczynski’s notes for a quick overview of these two tests. It furthermore makes use of code by Dunfield, Hoffman, Licata. The code to compute the isomorphism signature was ported over from Regina.
This verification code was contributed by Matthias Goerner.
The canonical retriangulation and the isometry signature¶
The canonical retriangulation is a close relative to the canonical cell decomposition defined by Epstein and Penner. Like the canonical cell decomposition, it is intrinsic to a hyperbolic manifold M and is (up to combinatorial isomorphism relabeling the tetrahedra and vertices) completely determined by the isometry type of a hyperbolic manifold. Unlike the canonical cell decomposition, the canonical retriangulation always conists entirely of tetrahedra which makes it more amenable for many computations by SnapPy.
If the canonical cell decompositon of manifold M has only tetrahedral cells,
we define the canonical retriangulation to be the canonical cell decomposition.
In this case, the canonical retriangulation consists of ideal hyperbolic
tetrahedra and the
canonical_retriangulation method returns a
SnapPy manifold. Example:
sage: M = Manifold("m015") sage: K = M.canonical_retriangulation(verified = True) sage: K.has_finite_vertices() # False iff all canonical cells tetrahedral False
If the canonical cell decomposition has non-tetrahedral cells, we turn it into
a topological triangulation as follows: pick a point (called center) in each
3-cell. “Suspend” each 2-cell (which is an ideal n-gon) between
the centers of the two neighboring 3-cells. These suspensions form a
decomposition of M into topological “diamonds”. Each diamond can be split along
its central axis into n tetrahedra. This introduces finite vertices, thus
verified_canonical_retriangulation method returns only a SnapPy
triangulation. Example (canonical cell is a cube):
sage: M = Manifold("m412") sage: K = M.canonical_retriangulation(verified = True) sage: K.has_finite_vertices() True
The canonical retriangulation can be used to certifiably find all isometries of a manifold:
sage: K.isomorphisms_to(K) [0 -> 1 1 -> 0 [1 0] [1 0] [0 1] [0 1] Extends to link, ... Extends to link] sage: len(K.isomorphisms_to(K)) 8
Recall that the isomorphism signature is a complete invariant of the combinatorial isomorphism type of a triangulation that was defined by Burton. We can compute the isomorphism signature of the canonical retriangulation:
sage: Manifold("m003").canonical_retriangulation(verified = True).isomorphism_signature() 'cPcbbbdxm'
The resulting invariant was called isometry signature by Goerner and, for convenience, can be accessed by:
sage: Manifold("m003").isometry_signature(verified = True) 'cPcbbbdxm'
It is a complete invariant of the isometry type of a hyperbolic manifold. Thus it can be used to easily identify isometric manifolds (here, the last two manifolds have the same isometry signature and thus have to be isomorphic):
sage: Manifold("m003").isometry_signature(verified = True) 'cPcbbbdxm' sage: Manifold("m004").isometry_signature(verified = True) 'cPcbbbiht' sage: Manifold("4_1").isometry_signature(verified = True) 'cPcbbbiht' sage: Manifold("m004").isometry_signature(verified = True) == Manifold("4_1").isometry_signature(verified = True) True
Other applications of the canonical retriangulation include the detection of 2-bridge knots.
Methods for verified computaions¶
verify_hyperbolicity(manifold, verbose=False, bits_prec=53, holonomy=False, fundamental_group_args=, lift_to_SL=True)¶
Given an orientable SnapPy Manifold, verifies its hyperbolicity. Similar to HIKMOT’s
verify_hyperbolicity(), the result is either
(False, )if verification failed.
listOfShapesIntervalsis a list of complex intervals (elements in sage’s
ComplexIntervalField) certified to contain the true shapes for the hyperbolic manifold.
Higher precision intervals can be obtained by setting
sage: from snappy import Manifold sage: M = Manifold("m019") sage: M.verify_hyperbolicity() # doctest: +ELLIPSIS (True, [0.780552527850...? + 0.914473662967...?*I, 0.780552527850...? + 0.91447366296773?*I, 0.4600211755737...? + 0.6326241936052...?*I]) sage: M = Manifold("t02333(3,4)") sage: M.verify_hyperbolicity() # doctest: +ELLIPSIS (True, [2.1521881536...? + 0.284940667...?*I, 1.92308491369? + 1.1036070150...?*I, 0.014388591584? + 0.143084469681?*I, -2.5493670288? + 3.7453498408?*I, 0.142120333822? + 0.176540027036?*I, 0.504866865...? + 0.82829881681?*I, 0.50479249917? + 0.98036162786?*I, -0.5894957050...? + 0.81267480427?*I])
One can instead get a holonomy representation associated to the verified hyperbolic structure. This representation takes values in 2x2 matrices with entries in the
sage: M = Manifold("m004(1,2)") sage: success, rho = M.verify_hyperbolicity(holonomy=True) sage: success True sage: trace = rho('aaB').trace(); trace # doctest: +ELLIPSIS -0.111862...? + 3.853612...?*I sage: (trace - 2).contains_zero() False sage: (rho('aBAbaabAB').trace() - 2).contains_zero() True
Here, there is provably a fixed holonomy representation rho0 from the fundamental group G of M to SL(2, C) so that for each element g of G the matrix rho0(g) is contained in rho(g). In particular, the above constitutes a proof that the word ‘aaB’ is non-trivial in G. In contrast, the final computation is consistent with ‘aBAbaabAB’ being trivial in G, but does not prove this.
A non-hyperbolic manifold (
Falseindicates that the manifold might not be hyperbolic but does not certify non-hyperbolicity. Sometimes, hyperbolicity can only be verified after increasing the precision):
sage: M = Manifold("4_1(1,0)") sage: M.verify_hyperbolicity() (False, )
Under the hood, the function will call the
CertifiedShapesEngineto produce intervals certified to contain a solution to the rectangular gluing equations. It then calls
check_logarithmic_gluing_equations_and_positively_oriented_tetsto verify that the logarithmic gluing equations are fulfilled and that all tetrahedra are positively oriented.
verified_canonical_retriangulation(M, interval_bits_precs=[53, 212], exact_bits_prec_and_degrees=[(212, 10), (1000, 20), (2000, 20)], verbose=False)¶
Given some triangulation of a cusped (possibly non-orientable) manifold
M, return its canonical retriangulation. Return
Noneif it could not certify the result.
To compute the canonical retriangulation, it first prepares the manifold (filling all Dehn-filled cusps and trying to find a proto-canonical triangulation). It then tries to certify the canonical triangulation using interval arithmetics. If this fails, it uses snap (using LLL-algorithm) to guess exact representations of the shapes in the shape field and then certifies that it found the proto-canonical triangulation and determines the transparent faces to construct the canonical retriangulation.
The optional arguments are:
interval_bits_precs: a list of precisions used to try to certify the canonical triangulation using intervals. By default, it first tries to certify using 53 bits precision. If it failed, it tries 212 bits precision next. If it failed again, it moves on to trying exact arithmetics.
exact_bits_prec_and_degrees: a list of pairs (precision, maximal degree) used when the LLL-algorithm is trying to find the defining polynomial of the shape field. Similar to
interval_bits_precs, each pair is tried until we succeed.
True, print out additional information.
The exact arithmetics can take a long time. To circumvent it, use
exact_bits_prec_and_degrees = None.
More information on the canonical retriangulation can be found in the SnapPea kernel
canonize_part_2.cand in Section 3.1 of Fominykh, Garoufalidis, Goerner, Tarkaev, Vesnin.
Canonical cell decompostion of
m004has 2 tetrahedral cells:
sage: from snappy import Manifold sage: M = Manifold("m004") sage: K = verified_canonical_retriangulation(M) sage: K.has_finite_vertices() False sage: K.num_tetrahedra() 2
Canonical cell decomposition of
m137is not tetrahedral:
sage: M = Manifold("m137") sage: K = verified_canonical_retriangulation(M) sage: K.has_finite_vertices() True sage: K.num_tetrahedra() 18
Canonical cell decomposition of
m412is a cube and has exactly 8 symmetries:
sage: M = Manifold("m412") sage: K = verified_canonical_retriangulation(M) sage: K.has_finite_vertices() True sage: K.num_tetrahedra() 12 sage: len(K.isomorphisms_to(K)) 8
Burton’s example of
x103which are actually isometric but SnapPea fails to show so. We certify the canonical retriangulation and find them isomorphic:
sage: M = Manifold('x101'); K = verified_canonical_retriangulation(M) sage: N = Manifold('x103'); L = verified_canonical_retriangulation(N) sage: len(K.isomorphisms_to(L)) > 0 True
Avoid potentially expensive exact arithmetics (return
Nonebecause it has non-tetrahedral cells so interval arithmetics can’t certify it):
sage: M = Manifold("m412") sage: verified_canonical_retriangulation(M, exact_bits_prec_and_degrees = None)