Kernel: SageMath 9.5

In this notebook we verify that all links (except the 5 stated in Proposition 3.1) in the two parameter family K_nm are hyperbolic. We defined K_nm via the surgery description L12n1739(-1,2n+m+3)(0,0)(1,n+1). (The different signs stem from the fact that L12n1739 is the mirror of the surgery description from our paper.) Now the idea is to use Gromov-Thurston's 2pi-Theorem to see that all long fillings are directly hyperbolic and check the remaining short fillings directly.

In [1]:
import snappy
In [2]:
L=snappy.Manifold('L12n1739') L.verify_hyperbolicity()[0]
Out[2]:
True
In [3]:
L.dehn_fill([(-1,5),(0,0),(1,2)]) L.identify()
Out[3]:
[o9_30634(0,0), K9_449(0,0)]
In [4]:
L.is_isometric_to(snappy.Manifold('o9_30634'),return_isometries=True)
Out[4]:
[0 -> 0 [1 2] [0 1] Extends to link, 0 -> 0 [-1 -2] [ 0 -1] Extends to link]
In [5]:
L=snappy.Manifold('L12n1739') L.short_slopes(length=6.3,verified=True)
Out[5]:
[[(1, 0), (-2, 1), (-1, 1), (0, 1), (1, 1), (-1, 2), (1, 2), (-1, 3)], [(1, 0), (-5, 1), (-4, 1), (-3, 1), (-2, 1), (-1, 1), (0, 1), (1, 1), (-5, 2), (-3, 2)], [(1, 0), (-2, 1), (-1, 1), (0, 1), (1, 1), (2, 1), (-1, 2), (1, 2)]]

Thus it follows that if (n+1 is not -2,-1,0,1,2) and (2n+m+3 is not -3,-2,-1,0,1,2) then K_nm is hyperbolic.

In the other cases, we first observe that L(0,0(0,0)(1,0) is the T(4,2) torus link. And thus L(1,k)(0,0)(1,0) is the T(-2k-1,2) torus knot.

For the remaining short slopes we first fill one remaining component permanently and then use the 2pi-Theorem again to get a finite list of slopes that might not be hyperbolic.

In [6]:
#The short reciprocal integer slopes of cusps 0 and 2. slopes0=[(-1, 1), (1, 1), (-1, 2), (1, 2), (-1, 3),(1,0)] slopes2=[(-1, 1), (1, 1), (-1, 2), (1, 2)] unclear_slopes=[] for s0 in slopes0: L.dehn_fill(s0,0) F=L.filled_triangulation() short=F.short_slopes(length=6.3,verified=True)[1] for s2 in short: if abs(s2[0])==1: if abs(s2[1])!=0: unclear_slopes.append([s0,(0,0),s2]) L.dehn_fill((0,0),0) for s2 in slopes2: L.dehn_fill(s2,2) F=L.filled_triangulation() short=F.short_slopes(length=6.3,verified=True)[0] for s0 in short: if abs(s0[0])==1: if abs(s0[1])!=0: unclear_slopes.append([s0,(0,0),s2]) L.dehn_fill((0,0),2) unclear_slopes
Out[6]:
[[(-1, 1), (0, 0), (-1, 1)], [(-1, 1), (0, 0), (1, 1)], [(-1, 1), (0, 0), (1, 2)], [(1, 1), (0, 0), (-1, 1)], [(1, 1), (0, 0), (1, 1)], [(1, 1), (0, 0), (-1, 2)], [(1, 1), (0, 0), (1, 2)], [(-1, 2), (0, 0), (-1, 1)], [(-1, 2), (0, 0), (1, 1)], [(-1, 2), (0, 0), (-1, 2)], [(-1, 2), (0, 0), (1, 2)], [(1, 2), (0, 0), (-1, 1)], [(1, 2), (0, 0), (1, 1)], [(1, 2), (0, 0), (-1, 2)], [(1, 2), (0, 0), (1, 2)], [(-1, 3), (0, 0), (-1, 1)], [(-1, 3), (0, 0), (1, 1)], [(-1, 3), (0, 0), (-1, 2)], [(-1, 3), (0, 0), (1, 2)], [(1, 0), (0, 0), (-1, 1)], [(1, 0), (0, 0), (1, 1)], [(1, 0), (0, 0), (-1, 2)], [(-1, 1), (0, 0), (-1, 1)], [(1, 1), (0, 0), (-1, 1)], [(-1, 2), (0, 0), (-1, 1)], [(1, 2), (0, 0), (-1, 1)], [(1, 3), (0, 0), (-1, 1)], [(1, 4), (0, 0), (-1, 1)], [(-1, 1), (0, 0), (1, 1)], [(1, 1), (0, 0), (1, 1)], [(-1, 2), (0, 0), (1, 1)], [(-1, 3), (0, 0), (1, 1)], [(-1, 4), (0, 0), (1, 1)], [(-1, 5), (0, 0), (1, 1)], [(-1, 1), (0, 0), (-1, 2)], [(1, 1), (0, 0), (-1, 2)], [(-1, 2), (0, 0), (-1, 2)], [(1, 2), (0, 0), (-1, 2)], [(-1, 3), (0, 0), (-1, 2)], [(1, 3), (0, 0), (-1, 2)], [(-1, 1), (0, 0), (1, 2)], [(1, 1), (0, 0), (1, 2)], [(-1, 2), (0, 0), (1, 2)], [(1, 2), (0, 0), (1, 2)], [(-1, 3), (0, 0), (1, 2)], [(-1, 4), (0, 0), (1, 2)]]
In [7]:
len(unclear_slopes)
Out[7]:
46

We are left with checking these 46 slopes. We first try to verify that they are hyperbolic via SnapPy.

In [8]:
def all_positive(manifold): ''' Checks if the solution type of a triangulation is positive. ''' return manifold.solution_type() == 'all tetrahedra positively oriented' def find_positive_triangulations(manifold,number=1,tries=100): ''' Searches for one triangulation with a positive solution type. (Or if number is set to a different value also for different such triangulations.) ''' M = manifold.copy() pos_triangulations=[] for i in range(tries): if all_positive(M): pos_triangulations.append(M) if len(pos_triangulations)==number: return pos_triangulations break M.randomize() for d in M.dual_curves(max_segments=500): X = M.drill(d) X = X.filled_triangulation() X.dehn_fill((1,0),-1) for i in range(tries): if all_positive(X): pos_triangulations.append(X) if len(pos_triangulations)==number: return pos_triangulations break X.randomize() # In the closed case, here is another trick. if all(not c for c in M.cusp_info('is_complete')): for i in range(tries): # Drills out a random edge X = M.__class__(M.filled_triangulation()) if all_positive(X): pos_triangulations.append(X) if len(pos_triangulations)==number: return pos_triangulations break M.randomize() return pos_triangulations
In [9]:
still_unclear=[] for s in unclear_slopes: L.dehn_fill(s) try: P=find_positive_triangulations(L,number=1,tries=100)[0] except (IndexError,snappy.SnapPeaFatalError): P=L hyp=P.verify_hyperbolicity()[0] print(L,hyp) if hyp==False: still_unclear.append(s)
Out[9]:
L12n1739(-1,1)(0,0)(-1,1) False L12n1739(-1,1)(0,0)(1,1) False L12n1739(-1,1)(0,0)(1,2) True L12n1739(1,1)(0,0)(-1,1) False L12n1739(1,1)(0,0)(1,1) True L12n1739(1,1)(0,0)(-1,2) True L12n1739(1,1)(0,0)(1,2) True L12n1739(-1,2)(0,0)(-1,1) True L12n1739(-1,2)(0,0)(1,1) False L12n1739(-1,2)(0,0)(-1,2) True L12n1739(-1,2)(0,0)(1,2) True L12n1739(1,2)(0,0)(-1,1) False L12n1739(1,2)(0,0)(1,1) True L12n1739(1,2)(0,0)(-1,2) True L12n1739(1,2)(0,0)(1,2) True L12n1739(-1,3)(0,0)(-1,1) True L12n1739(-1,3)(0,0)(1,1) False L12n1739(-1,3)(0,0)(-1,2) True L12n1739(-1,3)(0,0)(1,2) True L12n1739(1,0)(0,0)(-1,1) False L12n1739(1,0)(0,0)(1,1) True L12n1739(1,0)(0,0)(-1,2) True L12n1739(-1,1)(0,0)(-1,1) True L12n1739(1,1)(0,0)(-1,1) False L12n1739(-1,2)(0,0)(-1,1) True L12n1739(1,2)(0,0)(-1,1) False L12n1739(1,3)(0,0)(-1,1) True L12n1739(1,4)(0,0)(-1,1) True L12n1739(-1,1)(0,0)(1,1) False L12n1739(1,1)(0,0)(1,1) True L12n1739(-1,2)(0,0)(1,1) False L12n1739(-1,3)(0,0)(1,1) False L12n1739(-1,4)(0,0)(1,1) True L12n1739(-1,5)(0,0)(1,1) True L12n1739(-1,1)(0,0)(-1,2) True L12n1739(1,1)(0,0)(-1,2) True L12n1739(-1,2)(0,0)(-1,2) True L12n1739(1,2)(0,0)(-1,2) True L12n1739(-1,3)(0,0)(-1,2) True L12n1739(1,3)(0,0)(-1,2) True L12n1739(-1,1)(0,0)(1,2) True L12n1739(1,1)(0,0)(1,2) True L12n1739(-1,2)(0,0)(1,2) True L12n1739(1,2)(0,0)(1,2) True L12n1739(-1,3)(0,0)(1,2) True L12n1739(-1,4)(0,0)(1,2) True
In [10]:
still_unclear
Out[10]:
[[(-1, 1), (0, 0), (-1, 1)], [(-1, 1), (0, 0), (1, 1)], [(1, 1), (0, 0), (-1, 1)], [(-1, 2), (0, 0), (1, 1)], [(1, 2), (0, 0), (-1, 1)], [(-1, 3), (0, 0), (1, 1)], [(1, 0), (0, 0), (-1, 1)], [(1, 1), (0, 0), (-1, 1)], [(1, 2), (0, 0), (-1, 1)], [(-1, 1), (0, 0), (1, 1)], [(-1, 2), (0, 0), (1, 1)], [(-1, 3), (0, 0), (1, 1)]]

Thus we are left with 13 knots in the family which are probably not hyperbolic.

Actually, SnapPy recognizes all of them as hyperbolic or torus knots.

In [11]:
for s in still_unclear: L.dehn_fill(s) F=L.filled_triangulation() print(L,F.identify())
Out[11]:
L12n1739(-1,1)(0,0)(-1,1) [m016(0,0), K3_1(0,0), K12n242(0,0)] L12n1739(-1,1)(0,0)(1,1) [10_124(0,0), K10n21(0,0)] L12n1739(1,1)(0,0)(-1,1) [8_19(0,0), K8n3(0,0)] L12n1739(-1,2)(0,0)(1,1) [8_19(0,0), K8n3(0,0)] L12n1739(1,2)(0,0)(-1,1) [5_1(0,0), K5a2(0,0)] L12n1739(-1,3)(0,0)(1,1) [5_1(0,0), K5a2(0,0)] L12n1739(1,0)(0,0)(-1,1) [10_124(0,0), K10n21(0,0)] L12n1739(1,1)(0,0)(-1,1) [8_19(0,0), K8n3(0,0)] L12n1739(1,2)(0,0)(-1,1) [5_1(0,0), K5a2(0,0)] L12n1739(-1,1)(0,0)(1,1) [10_124(0,0), K10n21(0,0)] L12n1739(-1,2)(0,0)(1,1) [8_19(0,0), K8n3(0,0)] L12n1739(-1,3)(0,0)(1,1) [5_1(0,0), K5a2(0,0)]

All the above knots are torus knots (or hyperbolic in the case of K12n242):

K5a2 = T(5,2)

K8n3 = T(4,3)

K10n21 = T(5,3)

In total we have shown the statement from Proposition 3.1.(1): K_nm is hyperbolic for any (n,m) except for (n,m)=(-1,k) for k an integer, or (n,m)=(0,0),(0,-1),(0,-2),(-2,1),(-2,0),(-2,-1)

And in all the above non-hyperbolic cases K_nm is a torus knot.