This is the code that searchs for a friend.

In [6]:
# Imports
import snappy
import regina
import csv
import sys
from IPython.display import display, clear_output #used as in-calculation feedback

# for timing
import time
# for exponential function
import math
# for random choices
import random

#### Snappy extensions #####

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):
        try:
            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()
        except (snappy.SnapPeaFatalError,RuntimeError):
            pass

    # 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

def better_is_isometric_to(X,Y,index=50,try_hard=False):
    """
    Returns True if X and Y are isometric.
    Returns False if X and Y appear to be different.
     """ 
    for i in (0,index):
        w=False
        try:
            w=X.is_isometric_to(Y)
            if w==True:
                return w
        except (RuntimeError,snappy.SnapPeaFatalError):
            pass
        X.randomize()
        Y.randomize()
    if try_hard:
        pos_triang_X=find_positive_triangulations(X,number=1,tries=index)
        pos_triang_Y=find_positive_triangulations(Y,number=1,tries=index)
        for X in pos_triang_X:
            for Y in pos_triang_Y:
                w=better_is_isometric_to(X,Y,index=100,try_hard=False)
                if w==True:
                    return w
    return w

# Checking for knot complements

def is_homology_solid_torus(manifold):
    '''
    Checks if the input manifold has homology Z.
    '''
    M=snappy.Manifold(manifold)
    if M.homology().coefficients!=[0]:
        return False
    return True

def is_knot_complement(manifold,index=2):
    '''
    Checks the short fillings to be S3.
    '''
    assert manifold.num_cusps() == 1
    if manifold.homology().elementary_divisors() != [0]:
        return False
    try:
        slopes = manifold.short_slopes(3.5)[0]
    except RuntimeError:
        slopes = []
    (a, b) = manifold.homological_longitude()
    slopes = [s for s in slopes if abs(a*s[1] - b*s[0]) == 1]
    for s in slopes:
        M = snappy.Triangulation(manifold)
        M.dehn_fill(s)
        if is_three_sphere(M,tries=index):
            return True
    return False


def is_three_sphere(manifold,tries=2):
    """
    True means the manifold is definitely S^3.

    False means it is *likely* not S^3.
    """
    T = manifold
    order = T.homology().order()
    if order == 'infinite' or order > 1:
        return False
    G = snappy.Manifold(T)
    if G.solution_type(enum=True) == 1:
         return False
    for i in range(tries):
        if T.fundamental_group().num_generators() == 0:
            return True
        F = T.filled_triangulation()
        if F.fundamental_group().num_generators() == 0:
            return True
        T.randomize()
    return False

def better_length_spectrum(manifold,max_length=5.0,index=10,high_precision=False):
    '''Computes the length spectrum of the input manifold up to the given max_length. 
    Index gives the number of tries and high_precision increases the precision.'''
    M=snappy.Manifold(manifold)
    if high_precision:
        M=M.high_precision()
    for i in range(index):
        try:
            return M.length_spectrum(cutoff=max_length,include_words=True)
        except RuntimeError:
            M.randomize()
    return False

#regina functions

def to_regina(data):
    '''
    This function was written by Dunfield.
    It sends a SnapPy triangulation to regina.
    '''
    if hasattr(data, '_to_string'):
        data = data._to_string()
    if isinstance(data, str):
        if data.find('(') > -1:
            data = closed_isosigs(data)[0]
        return regina.Triangulation3(data)
    assert isinstance(data, regina.Triangulation3)
    return data

def display_check(sig, tri):
    iso_signatures.append(sig)
    if len(iso_signatures)>maximum:
        return True
        #It stops if we have too many signatures
    return False

def drill_edges(T,index=0,verbose=False,cores=1,max_submanifolds=100,max_triangulations=10,randomized=False):
    '''
    Takes as input a regina triangulation and drills out edges and returns a list of its signatures.
    '''
    global iso_signatures
    iso_signatures=[]
    global maximum
    maximum=max_triangulations 
    if index < 0:
        ctr=0
        while len(iso_signatures) < (-1)*index and ctr < 1000:
            ctr+=1
            T = randomise(T, 100, 2/T.size())
            if not T.isoSig() in iso_signatures:
                iso_signatures.append(T.isoSig())
    else:
        T.retriangulate(index,cores,display_check)
    if verbose:
        print('Found',len(iso_signatures),'triangulations')
    drilled=[]
    if randomized==False:
        for sig in iso_signatures:
            Y=regina.Triangulation3(sig)
            for e in range(Y.edges().size()):
                X=regina.Triangulation3(sig)
                X.pinchEdge(X.edge(e))
                if X.homology().isZ():
                    X.intelligentSimplify()
                    drilled.append(X.isoSig())
                    if len(drilled)>max_submanifolds:
                        if verbose:
                            print('Number of submanifolds found:',len(drilled))
                        return drilled
    if randomized==True:
        l=len(iso_signatures)
        for i in range(max_submanifolds):
            sig=iso_signatures[random.randint(0,l-1)]
            Y=regina.Triangulation3(sig)
            for e in range(Y.edges().size()):
                X=regina.Triangulation3(sig)
                X.pinchEdge(X.edge(e))
                if X.homology().isZ():
                    X.intelligentSimplify()
                    drilled.append(X.isoSig())
                    if len(drilled)>max_submanifolds:
                        if verbose:
                            print('Number of submanifolds found:',len(drilled))
                        return drilled
    if verbose:
        print('Number of submanifolds found:',len(drilled))
    return drilled

#####################################################################
#####################################################################
# functions for random walk
#####################################################################
#####################################################################

def choosemove(T, beta):
    x = random.random()
    if x < math.exp((-1)*beta*T.size()):
        a = 1
    else:
        a = 2
    # setup done
    # go up (2-3)
    # most triangles correspond to a valid move, no need to classify
    if a == 1:
        tri = random.choice(range(T.countTriangles()))
        if T.pachner(T.triangle(tri),True,False):
            S = regina.Triangulation3(T)
            S.pachner(S.triangle(tri),False,True)
            return S
    # go down
    elif a == 2:
        # get all possible 3-2 moves
        valid = []
        for e in range(T.countEdges()):
            if T.pachner(T.edge(e),True,False):
                valid.append(e)
        if valid != []:
            S = regina.Triangulation3(T)
            S.pachner(S.edge(random.choice(valid)),False,True)
            return S            
    # nothing worked
    return T

def randomise(T, steps, beta):
    # initialise number of steps
    st = 0
    while st < steps:
        st += 1
        T = choosemove(T,beta)
    return T

#####################################################################
#####################################################################
# end functions for random walk
#####################################################################
#####################################################################



def search_for_friend(knot,effort='low',max_number_of_friends=1,Regina=True,SnapPy_dual_curves=True,SnapPy_length_spectrum=True,MCMC=True,verbose=False):
    '''
    This functions takes as input a triangulation of the exterior of a knot K and searchs for friends of K. 
    (If it is not a knot exterior it still searchs for a knot F on S3 such that 0-surgery on F yields the 
    homological filling on K.)
    
    Method:
    First we create the 0-surgery K(0,1) of K.
    Then we create a list of knot complements in K(0,1). We use the 6-theorem to check if that knot complement 
    has a filling to S3 and thus represents a knot F in S3. If that knot appears to not be isometric to K,
    we return F. 
    WARNING: It is then not rigoursly proven that F and K are different. But that will usually be the case. 
    It needs to be double-checked for example using the volume or another knot invariant.
    
    There are three options to create the list of knot complements in K(0,1).
    
    (1) SnapPy_dual_curves=True: 
    This drills out dual curves of a triangulation of K(0,1)
    (which only works if the triangulation yields a hyperbolic structure).
    
    (2) SnapPy_length_spectrum=True:
    Uses the verified length spectrum computation of K(0,1) and drills out short geodesics from K(0,1).
    
    (3) Regina=True:
    This creates a one-vertex triangulation of K(0,1) in regina and then drills out edges of that triangulation. Uses
    Regina retriangulate function to go through Pachner graph in breadth first search

        
    (4) MCMC=True:
    Same as (3), but the next triangulation is found by a random walk rather than by breadth first search in the Pachner
    graph (as done by "retriangulate").
    
    If Regina is not installed put regina=False. In general it is recommended to use all three methods, since there
    exist friends that can only be found effectively with one of the methods.
    
    
    Options:
    We can put effort='low','medium', 'high' to choose pre-chosen values of parameters to search for friends.
    Or one can put effort=None and choose the parameters freely. See the documentation in the code for that.
    
    
    
    The other options affect the runtime and efficiency of the code:
     
     
     -- 
    How fast the code will run depends of course heavily on the input triangulation. 
    The default options are choosen for maximal efficiency. But if one wants to search harder for friends one 
    should increase the parameters. The following options have turned out to run reasonable fast and find 
    most friends on reasonable small examples.
    '''
    
    
    
    #We have the following parameters:
    #General:
    random=True #If true chooses random dual_curves, geodesics, edges to drill.
    random_upper_bound=100 #Number of random elements that we drill.
    exterior_index=2 #Number of tries to check if a drilled out object is a knot complement.
    try_hard=False #If True it searches very hard for an isometry of a potential friend to K. 
    isometry_index=5 #Number of tries to check if two manifolds are isometric
    
    #For drilling dual curves:
    max_segments=100 #Maximal number of segements in dual curves.
    upper_bound_dual_curves=2000 #An upper bound on the number of dual curves that we check.
    
    #For drilling geodesics
    max_length=5.0 #maximal length of a geodesic in the length spectrum.
    high_precision=False #If true uses high precision to compute the length spectrum.
    recursion_limit=50000 #The recursion limit for drilling out geodesics.
    upper_bound_geodesics=2000 #Upper bound on the number of geodesics we check
    
    #For drilling edges with regina:
    regina_simplify=False #Simplifies the input triangulation if set to True
    regina_retriangulate_index=2 #The maximal difference of the number of simplices of a triangulation from the input triangulation.
    regina_cores_used=1 #If this number gets increased regina uses more cores and the code runs quicker but might also crush your computer.
    max_regina_submanifolds=5000 #The maximal number of submanifolds that regina creates.
    maximal_number_of_Pachner_moves=250 #The maximal number of Pachner moves regina performs to create more triangulations.
    
        
    
    if effort=='low':
        random=False 
        random_upper_bound=100
        exterior_index=1 
        try_hard=False  
        isometry_index=1 
        max_segments=6 
        upper_bound_dual_curves=15 
        max_length=1.0 
        high_precision=False 
        recursion_limit=10000 
        upper_bound_geodesics=15 
        regina_simplify=True
        regina_retriangulate_index=0 
        regina_cores_used=1 
        max_regina_submanifolds=50 
        maximal_number_of_Pachner_moves=10
        rounds = 10
    
    if effort=='medium':
        random=False 
        random_upper_bound=100
        exterior_index=2 
        try_hard=False  
        isometry_index=2 
        max_segments=25 
        upper_bound_dual_curves=100 
        max_length=3.0 
        high_precision=False 
        recursion_limit=40000 
        upper_bound_geodesics=100 
        regina_simplify=True
        regina_retriangulate_index=0 
        regina_cores_used=1 
        max_regina_submanifolds=100 
        maximal_number_of_Pachner_moves=10
        rounds = 30
    
    if effort=='high':
        random=False 
        random_upper_bound=100
        exterior_index=2 
        try_hard=False  
        isometry_index=2 
        max_segments=50 
        upper_bound_dual_curves=250 
        max_length=4.0 
        high_precision=False 
        recursion_limit=50000 
        upper_bound_geodesics=250 
        regina_simplify=True
        regina_retriangulate_index=2 
        regina_cores_used=1 
        max_regina_submanifolds=5000 
        maximal_number_of_Pachner_moves=100
        rounds = 1000
        
    if verbose:
        print('We have choosen the following parameters to search for friends:')
        print('random',random)
        print('random_upper_bound',random_upper_bound)
        print('exterior_index',exterior_index) 
        print('try_hard',try_hard)  
        print('isometry_index',isometry_index) 
        print('max_segments',max_segments) 
        print('upper_bound_dual_curves',upper_bound_dual_curves) 
        print('max_length',max_length) 
        print('high_precision',high_precision) 
        print('recursion_limit',recursion_limit) 
        print('upper_bound_geodesics',upper_bound_geodesics)
        print('regina_simplify',regina_simplify)
        print('regina_retriangulate_index',regina_retriangulate_index)
        print('regina_cores_used',regina_cores_used) 
        print('max_regina_submanifolds',max_regina_submanifolds) 
        print('maximal_number_of_Pachner_moves',maximal_number_of_Pachner_moves)
        print('number of rounds for random walk',rounds)
        print('--------------')

    #M is the knot exterior and K the 0-filling
    M=snappy.Manifold(knot)
    K=snappy.Manifold(knot)
    if is_homology_solid_torus(K)==False:
        raise ValueError('The homology of K is not Z and thus it is not a knot in S3.')        
    K.dehn_fill(K.homological_longitude())
    
    #Lists of possible knot exteriors and friends
    possible_knot_exteriors=[]
    friends=[]
    
    ##### SNAPPY DUAL CURVES ######
    
    if SnapPy_dual_curves:
        dual_curves=K.dual_curves(max_segments=max_segments)
        
        if verbose:
            print('--------------')
            print('We check dual curves with SnapPy and search for a friend.')
            print('Number of dual curves:',len(dual_curves))
            
        if random==False:
            if verbose:
                print('We check all dual curves.')
            for c in dual_curves:
                try:
                    E=K.drill(c)
                    E=E.filled_triangulation()
                    if better_is_isometric_to(E,M,index=isometry_index)==False:
                        if is_homology_solid_torus(E)==True:
                            already_known=False
                            for X in possible_knot_exteriors:
                                if better_is_isometric_to(X,E,index=isometry_index):
                                    already_known=True
                                    break
                            if already_known==False:
                                if verbose:
                                    print('We found a new potential knot exterior:',E)
                                possible_knot_exteriors.append(E)
                                if verbose:
                                    print('Checking for knot complement:',E)
                                if is_knot_complement(E,index=exterior_index):
                                    if better_is_isometric_to(E,M,try_hard=try_hard)==False:
                                        already_known=False
                                        for X in friends:
                                            if better_is_isometric_to(X,E,index=isometry_index,try_hard=try_hard):
                                                already_known=True
                                                break
                                        if already_known==False:
                                            if verbose:
                                                print('We found a friend:',E)
                                            friends.append(E)
                                            if len(friends)>max_number_of_friends-1:
                                                if verbose:
                                                    print('Number of potential knot exteriors checked:',len(possible_knot_exteriors))
                                                    print('Number of friends found:',len(friends))
                                                return friends, dual_curve.index(c)  
                    if c.index>upper_bound_dual_curves:
                        break
                except:
                    pass
                    
        if random==True:
            if verbose:
                print('We check a random collection of dual curves.')
            for i in range(random_upper_bound):
                try:
                    c=dual_curves[random.randint(0,len(dual_curves)-1)]
                    E=K.drill(c)
                    E=E.filled_triangulation()
                    if better_is_isometric_to(E,M,index=isometry_index)==False:
                        if is_homology_solid_torus(E)==True:
                            already_known=False
                            for X in possible_knot_exteriors:
                                if better_is_isometric_to(X,E,index=isometry_index):
                                    already_known=True
                                    break
                            if already_known==False:
                                if verbose:
                                    print('We found a new potential knot exterior:',E)
                                possible_knot_exteriors.append(E)
                                if verbose:
                                    print('Checking for knot complement:',E)
                                if is_knot_complement(E,index=exterior_index):
                                    if better_is_isometric_to(E,M,try_hard=try_hard)==False:
                                        already_known=False
                                        for X in friends:
                                            if better_is_isometric_to(X,E,index=isometry_index,try_hard=try_hard):
                                                already_known=True
                                                break
                                        if already_known==False:
                                            if verbose:
                                                print('We found a friend:',E)
                                            friends.append(E)
                                            if len(friends)>max_number_of_friends-1:
                                                if verbose:
                                                    print('Number of potential knot exteriors checked:',len(possible_knot_exteriors))
                                                    print('Number of friends found:',len(friends))
                                                return friends 
                except:
                    pass
                                        
##### SNAPPY LENGTH SPECTRUM ######
    
    if SnapPy_length_spectrum:
        sys.setrecursionlimit(recursion_limit)
        
        if verbose:
            print('--------------')
            print('We check short geodescis with SnapPy and search for a friend.')
        
        # Compute the length spectrum
        spec=better_length_spectrum(K,max_length=max_length,index=10,high_precision=False)
    
        if spec==False:
            if verbose:
                print('We could not compute the length spectrum of the 0-surgery.')
        else:
            if verbose:
                print('Number of geodesics in the length spectrum:',len(spec))
            
            if random==False:
                if verbose:
                    print('We check all geodesics.')
       
                for c in spec:
                    try:
                        E=K.drill_word(c.word)
                        E=E.filled_triangulation()
                        if better_is_isometric_to(E,M,index=isometry_index)==False:
                            if is_homology_solid_torus(E)==True:
                                already_known=False
                                for X in possible_knot_exteriors:
                                    if better_is_isometric_to(X,E,index=isometry_index):
                                        already_known=True
                                        break
                                if already_known==False:
                                    possible_knot_exteriors.append(E)
                                    if is_knot_complement(E,index=exterior_index):
                                        if better_is_isometric_to(E,M,try_hard=try_hard)==False:
                                            already_known=False
                                            for X in friends:
                                                if better_is_isometric_to(X,E,index=isometry_index,try_hard=try_hard):
                                                    already_known=True
                                                    break
                                            if already_known==False:
                                                if verbose:
                                                    print('We found a friend:',E)
                                                friends.append(E)
                                                if len(friends)>max_number_of_friends-1:
                                                    if verbose:
                                                        print('Number of potential knot exteriors checked:',len(possible_knot_exteriors))
                                                        print('Number of friends found:',len(friends))
                                                    return friends  
                    except:
                        pass
                    if spec.index(c)>upper_bound_geodesics:
                        break
            if random==True:
                if verbose:
                    print('We check a random collection of geodesics.')
                    
                for i in range(random_upper_bound):
                    c=spec[random.randint(0,len(spec)-1)]
                    try:
                        E=K.drill_word(c.word)
                        E=E.filled_triangulation()
                        if better_is_isometric_to(E,M,index=isometry_index)==False:
                            if is_homology_solid_torus(E)==True:
                                already_known=False
                                for X in possible_knot_exteriors:
                                    if better_is_isometric_to(X,E,index=isometry_index):
                                        already_known=True
                                        break
                                if already_known==False:
                                    possible_knot_exteriors.append(E)
                                    if is_knot_complement(E,index=exterior_index):
                                        if better_is_isometric_to(E,M,try_hard=try_hard)==False:
                                            already_known=False
                                            for X in friends:
                                                if better_is_isometric_to(X,E,index=isometry_index,try_hard=try_hard):
                                                    already_known=True
                                                    break
                                            if already_known==False:
                                                if verbose:
                                                    print('We found a friend:',E)
                                                friends.append(E)
                                                if len(friends)>max_number_of_friends-1:
                                                    if verbose:
                                                        print('Number of potential knot exteriors checked:',len(possible_knot_exteriors))
                                                        print('Number of friends found:',len(friends))
                                                    return friends                
                    except:
                        pass
        
    ##### REGIN DRILL EDGES ######                 
    
    if Regina:
        if verbose:
            print('--------------')
            print('We drill out knots via Regina.')
            
        T=to_regina(K.filled_triangulation())
        if regina_simplify:
            T.intelligentSimplify()
            
        if random==False:
            if verbose:
                print('We check all edges.')
            sigs=drill_edges(T,index=regina_retriangulate_index,cores=regina_cores_used,max_submanifolds=max_regina_submanifolds,max_triangulations=maximal_number_of_Pachner_moves)
            if verbose:
                print('Total number of submanifolds found via regina:',len(sigs)) 
                
        if random==True:   
            if verbose:
                print('We check random edges.')
            sigs=drill_edges(T,index=regina_retriangulate_index,cores=regina_cores_used,max_submanifolds=max_regina_submanifolds,max_triangulations=maximal_number_of_Pachner_moves,randomized=True)
            if verbose:
                print('Total number of submanifolds found via regina:',len(sigs)) 

        for sig in sigs:
            try:
                T=regina.Triangulation3(sig)
                E=snappy.Manifold(T.snapPea())
                if better_is_isometric_to(E,M,index=isometry_index)==False:
                    if is_homology_solid_torus(E)==True:
                        already_known=False
                        for X in possible_knot_exteriors:
                            if better_is_isometric_to(X,E):
                                already_known=True
                                break
                        if already_known==False:
                            if verbose:
                                print('We found a new potential knot exterior:',E)
                            possible_knot_exteriors.append(E)
                            if verbose:
                                print('Checking for knot complement:',E)
                            if is_knot_complement(E,index=exterior_index):
                                if better_is_isometric_to(E,M,try_hard=try_hard)==False:
                                    already_known=False
                                    for X in friends:
                                        if better_is_isometric_to(X,E,index=isometry_index,try_hard=try_hard):
                                            already_known=True
                                            break
                                    if already_known==False:
                                        if verbose:
                                            print('We found a friend:',E)
                                        friends.append(E)
                                        if len(friends)>max_number_of_friends-1:
                                            if verbose:
                                                print('Number of potential knot exteriors checked:',len(possible_knot_exteriors))
                                                print('Number of friends found:',len(friends))
                                            return friends 
            except:
                pass

    ##### MCMC to replace retriangulation (more variance for other results -- hopefully) ######                 
    
    if MCMC:        
        if verbose:
            print('--------------')
            print('We drill out knots via Regina, using a random walk method to choose next triangulation.')
            
        T=to_regina(K.filled_triangulation())
        if regina_simplify:
            T.intelligentSimplify()

        if random==False:
            if verbose:
                print('We check all edges.')
            sigs=drill_edges(T,index=(-1)*rounds,cores=regina_cores_used,max_submanifolds=max_regina_submanifolds)
            if verbose:
                print('Total number of submanifolds found via regina:',len(sigs)) 
                
        if random==True:   
            if verbose:
                print('We check random edges.')
            sigs=drill_edges(T,index=(-1)*rounds,cores=regina_cores_used,randomized=True,max_submanifolds=max_regina_submanifolds)
            if verbose:
                print('Total number of submanifolds found via regina:',len(sigs)) 
        ctr=0
        print("found",len(sigs),"triangulations to check")
        for sig in sigs:
            try:
                T=regina.Triangulation3(sig)
                E=snappy.Manifold(T.snapPea())
                if better_is_isometric_to(E,M,index=isometry_index)==False:
                    if is_homology_solid_torus(E)==True:
                        already_known=False
                        for X in possible_knot_exteriors:
                            if better_is_isometric_to(X,E):
                                already_known=True
                                break
                        if already_known==False:
                            if verbose:
                                print('We found a new potential knot exterior:',E)
                            possible_knot_exteriors.append(E)
                            if verbose:
                                print('Checking for knot complement:',E)
                            if is_knot_complement(E,index=exterior_index):
                                if better_is_isometric_to(E,M,try_hard=try_hard)==False:
                                    already_known=False
                                    for X in friends:
                                        if better_is_isometric_to(X,E,index=isometry_index,try_hard=try_hard):
                                            already_known=True
                                            break
                                    if already_known==False:
                                        if verbose:
                                            print('We found a friend:',E)
                                        friends.append(E)
                                        if len(friends)>max_number_of_friends-1:
                                            if verbose:
                                                print('Number of potential knot exteriors checked:',len(possible_knot_exteriors))
                                                print('Number of friends found:',len(friends))
                                            return friends
            except:
                pass


    if verbose:
        print('Number of potential knot exteriors checked:',len(possible_knot_exteriors))
        print('Number of friends found:',len(friends))        
    
    return friends
            
    
def find_S3_filling(manifold,index=2):
    '''
    Checks the short fillings to be S3.
    '''
    
    assert manifold.num_cusps() == 1
    if manifold.homology().elementary_divisors() != [0]:
        return False

    try:
        slopes = manifold.short_slopes(3.5)[0]
    except RuntimeError:
        slopes = []

    (a, b) = manifold.homological_longitude()
    slopes = [s for s in slopes if abs(a*s[1] - b*s[0]) == 1]
    for s in slopes:
        M = snappy.Triangulation(manifold)
        M.dehn_fill(s)
        if is_three_sphere(M,tries=index):
            return s
    return False


            
    
def create_diagram(knot_complement,verbose=False):
    '''
    Takes a list of complements of a knot and creates a diagram.
    '''
    M=knot_complement
    M.dehn_fill((0,0))
    D=False
    try:
        M.set_peripheral_curves('shortest')
    except:
        pass
    try:
        M.dehn_fill((1,0))
        if is_three_sphere(M):
            D=M.exterior_to_link()
            if D!=False:
                D.simplify('global')
                PD_friend=D.PD_code()
                return PD_friend
            
        M.dehn_fill((0,0))
        M.dehn_fill(find_S3_filling(M))
        D=M.exterior_to_link()
        if D!=False:
            D.simplify('global')
            PD_friend=D.PD_code()
            return PD_friend
    except:
        pass

    print('COULD NOT FIND A DIAGRAM!')
    return D

Examples:

In [7]:
exteriors=search_for_friend('K8a4',verbose=True)
We have choosen the following parameters to search for friends:
random False
random_upper_bound 100
exterior_index 1
try_hard False
isometry_index 1
max_segments 6
upper_bound_dual_curves 15
max_length 1.00000000000000
high_precision False
recursion_limit 10000
upper_bound_geodesics 15
regina_simplify True
regina_retriangulate_index 0
regina_cores_used 1
max_regina_submanifolds 50
maximal_number_of_Pachner_moves 10
number of rounds for random walk 10
--------------
--------------
We check dual curves with SnapPy and search for a friend.
Number of dual curves: 20
We check all dual curves.
We found a new potential knot exterior: K8a4-6_filled(0,0)
Checking for knot complement: K8a4-6_filled(0,0)
We found a new potential knot exterior: K8a4-8_filled(0,0)
Checking for knot complement: K8a4-8_filled(0,0)
We found a new potential knot exterior: K8a4-10_filled(0,0)
Checking for knot complement: K8a4-10_filled(0,0)
We found a friend: K8a4-10_filled(0,0)
Number of potential knot exteriors checked: 3
Number of friends found: 1
--------------
We check short geodescis with SnapPy and search for a friend.
Number of geodesics in the length spectrum: 2
We check all geodesics.
--------------
We drill out knots via Regina.
We check all edges.
Total number of submanifolds found via regina: 10
--------------
We drill out knots via Regina, using a random walk method to choose next triangulation.
We check all edges.
Total number of submanifolds found via regina: 51
found 51 triangulations to check
Number of potential knot exteriors checked: 3
Number of friends found: 1
In [8]:
start_time=time.time()
with_friends=[]

for c in range(5,10):
    for K in snappy.HTLinkExteriors(knots_vs_links='knots',crossings=c):
        display('Currently checking '+K.name())
        exteriors=search_for_friend(K,verbose=True)
        for X in exteriors:
            D=create_diagram(X)
            with_friends.append([K.name(),D])
        clear_output(wait=True)
        
print('Number of friends found:',len(with_friends))
print('Minutes taken:',(time.time()-start_time)/60)
Number of friends found: 16
Minutes taken: 1.9175494194030762
In [9]:
with_friends
Out[9]:
[['K6a2',
  [(11, 4, 12, 5),
   (22, 5, 23, 6),
   (9, 26, 10, 27),
   (33, 11, 34, 10),
   (16, 26, 17, 25),
   (14, 32, 15, 31),
   (17, 38, 18, 39),
   (20, 35, 21, 36),
   (23, 31, 24, 30),
   (0, 15, 1, 16),
   (6, 21, 7, 22),
   (7, 35, 8, 34),
   (29, 19, 30, 18),
   (28, 37, 29, 38),
   (13, 2, 14, 3),
   (27, 8, 28, 9),
   (3, 12, 4, 13),
   (39, 24, 0, 25),
   (1, 32, 2, 33),
   (36, 19, 37, 20)]],
 ['K7a2',
  [(41, 15, 42, 14),
   (11, 45, 12, 44),
   (30, 13, 31, 14),
   (15, 5, 16, 4),
   (16, 27, 17, 28),
   (33, 23, 34, 22),
   (18, 2, 19, 1),
   (2, 18, 3, 17),
   (40, 26, 41, 25),
   (3, 29, 4, 28),
   (26, 6, 27, 5),
   (36, 53, 37, 0),
   (0, 37, 1, 38),
   (39, 6, 40, 7),
   (24, 49, 25, 50),
   (31, 51, 32, 50),
   (51, 13, 52, 12),
   (52, 43, 53, 44),
   (47, 35, 48, 34),
   (48, 21, 49, 22),
   (23, 33, 24, 32),
   (9, 47, 10, 46),
   (8, 35, 9, 36),
   (7, 21, 8, 20),
   (29, 43, 30, 42),
   (19, 39, 20, 38),
   (45, 11, 46, 10)]],
 ['K8a4',
  [(31, 14, 32, 15),
   (30, 2, 31, 1),
   (27, 20, 28, 21),
   (18, 29, 19, 30),
   (35, 29, 36, 28),
   (25, 4, 26, 5),
   (3, 24, 4, 25),
   (10, 22, 11, 21),
   (34, 19, 35, 20),
   (17, 9, 18, 8),
   (16, 37, 17, 0),
   (6, 16, 7, 15),
   (12, 6, 13, 5),
   (36, 9, 37, 10),
   (7, 0, 8, 1),
   (2, 34, 3, 33),
   (13, 32, 14, 33),
   (23, 26, 24, 27),
   (22, 12, 23, 11)]],
 ['K8a10',
  [(8, 17, 9, 18),
   (4, 34, 5, 33),
   (9, 29, 10, 28),
   (12, 36, 13, 35),
   (38, 16, 39, 15),
   (14, 0, 15, 39),
   (32, 6, 33, 5),
   (19, 10, 20, 11),
   (0, 14, 1, 13),
   (2, 25, 3, 26),
   (11, 22, 12, 23),
   (36, 22, 37, 21),
   (29, 17, 30, 16),
   (30, 8, 31, 7),
   (26, 24, 27, 23),
   (20, 38, 21, 37),
   (24, 3, 25, 4),
   (18, 28, 19, 27),
   (1, 34, 2, 35),
   (6, 32, 7, 31)]],
 ['K8a10',
  [(49, 6, 50, 7),
   (58, 14, 59, 13),
   (12, 29, 13, 30),
   (10, 47, 11, 48),
   (15, 61, 16, 60),
   (14, 43, 15, 44),
   (39, 18, 40, 19),
   (20, 37, 21, 38),
   (2, 18, 3, 17),
   (0, 25, 1, 26),
   (63, 40, 0, 41),
   (59, 44, 60, 45),
   (53, 4, 54, 5),
   (19, 57, 20, 56),
   (26, 61, 27, 62),
   (31, 49, 32, 48),
   (32, 9, 33, 10),
   (3, 22, 4, 23),
   (54, 22, 55, 21),
   (5, 52, 6, 53),
   (38, 55, 39, 56),
   (36, 52, 37, 51),
   (34, 7, 35, 8),
   (8, 33, 9, 34),
   (50, 36, 51, 35),
   (57, 28, 58, 29),
   (45, 31, 46, 30),
   (41, 62, 42, 63),
   (46, 11, 47, 12),
   (24, 1, 25, 2),
   (27, 43, 28, 42),
   (23, 16, 24, 17)]],
 ['K9a1',
  [(35, 7, 36, 6),
   (22, 9, 23, 10),
   (58, 13, 59, 14),
   (79, 9, 80, 8),
   (5, 85, 6, 84),
   (23, 33, 24, 32),
   (21, 68, 22, 69),
   (49, 24, 50, 25),
   (0, 26, 1, 25),
   (59, 29, 60, 28),
   (78, 33, 79, 34),
   (36, 81, 37, 82),
   (50, 78, 51, 77),
   (57, 72, 58, 73),
   (82, 66, 83, 65),
   (85, 76, 0, 77),
   (64, 84, 65, 83),
   (75, 16, 76, 17),
   (67, 54, 68, 55),
   (34, 52, 35, 51),
   (73, 62, 74, 63),
   (14, 61, 15, 62),
   (7, 52, 8, 53),
   (37, 67, 38, 66),
   (4, 17, 5, 18),
   (39, 21, 40, 20),
   (63, 18, 64, 19),
   (56, 20, 57, 19),
   (27, 61, 28, 60),
   (12, 42, 13, 41),
   (71, 41, 72, 40),
   (29, 42, 30, 43),
   (43, 30, 44, 31),
   (45, 71, 46, 70),
   (44, 12, 45, 11),
   (26, 2, 27, 1),
   (74, 3, 75, 4),
   (15, 2, 16, 3),
   (80, 54, 81, 53),
   (10, 48, 11, 47),
   (55, 39, 56, 38),
   (69, 47, 70, 46),
   (31, 48, 32, 49)]],
 ['K9a3',
  [(35, 22, 36, 23),
   (23, 34, 24, 35),
   (13, 26, 14, 27),
   (24, 4, 25, 3),
   (20, 2, 21, 1),
   (0, 26, 1, 25),
   (16, 8, 17, 7),
   (39, 8, 40, 9),
   (5, 38, 6, 39),
   (32, 38, 33, 37),
   (28, 0, 29, 41),
   (27, 14, 28, 15),
   (31, 18, 32, 19),
   (6, 18, 7, 17),
   (2, 22, 3, 21),
   (36, 12, 37, 11),
   (19, 12, 20, 13),
   (10, 34, 11, 33),
   (9, 4, 10, 5),
   (15, 30, 16, 31),
   (40, 30, 41, 29)]],
 ['K9a3',
  [(12, 36, 13, 35),
   (14, 32, 15, 31),
   (16, 63, 17, 64),
   (49, 30, 50, 31),
   (51, 34, 52, 35),
   (47, 65, 48, 64),
   (4, 40, 5, 39),
   (27, 63, 28, 62),
   (29, 48, 30, 49),
   (28, 16, 29, 15),
   (18, 26, 19, 25),
   (45, 24, 46, 25),
   (0, 17, 1, 18),
   (65, 47, 0, 46),
   (1, 27, 2, 26),
   (55, 21, 56, 20),
   (8, 21, 9, 22),
   (37, 52, 38, 53),
   (36, 12, 37, 11),
   (9, 55, 10, 54),
   (33, 50, 34, 51),
   (23, 38, 24, 39),
   (7, 43, 8, 42),
   (56, 43, 57, 44),
   (32, 14, 33, 13),
   (58, 6, 59, 5),
   (41, 7, 42, 6),
   (40, 57, 41, 58),
   (22, 60, 23, 59),
   (61, 10, 62, 11),
   (60, 54, 61, 53),
   (44, 4, 45, 3),
   (19, 2, 20, 3)]],
 ['K9a4',
  [(28, 46, 29, 45),
   (58, 13, 59, 14),
   (23, 69, 24, 68),
   (26, 93, 27, 94),
   (15, 100, 16, 101),
   (29, 112, 30, 113),
   (27, 1, 28, 0),
   (65, 44, 66, 45),
   (60, 78, 61, 77),
   (67, 95, 68, 94),
   (57, 98, 58, 99),
   (80, 102, 81, 101),
   (62, 116, 63, 115),
   (66, 121, 67, 0),
   (70, 22, 71, 21),
   (75, 19, 76, 18),
   (79, 17, 80, 16),
   (110, 2, 111, 1),
   (109, 92, 110, 93),
   (111, 47, 112, 46),
   (119, 11, 120, 10),
   (120, 83, 121, 84),
   (3, 91, 4, 90),
   (6, 114, 7, 113),
   (7, 64, 8, 65),
   (2, 32, 3, 31),
   (8, 86, 9, 85),
   (49, 89, 50, 88),
   (43, 84, 44, 85),
   (42, 10, 43, 9),
   (48, 5, 49, 6),
   (12, 53, 13, 54),
   (117, 53, 118, 52),
   (39, 55, 40, 54),
   (97, 56, 98, 57),
   (99, 14, 100, 15),
   (96, 82, 97, 81),
   (118, 41, 119, 42),
   (55, 39, 56, 38),
   (11, 41, 12, 40),
   (82, 37, 83, 38),
   (95, 37, 96, 36),
   (91, 32, 92, 33),
   (86, 64, 87, 63),
   (87, 114, 88, 115),
   (51, 117, 52, 116),
   (50, 61, 51, 62),
   (47, 31, 48, 30),
   (71, 105, 72, 104),
   (24, 107, 25, 108),
   (108, 25, 109, 26),
   (106, 70, 107, 69),
   (17, 77, 18, 76),
   (35, 103, 36, 102),
   (33, 74, 34, 75),
   (34, 20, 35, 19),
   (20, 74, 21, 73),
   (105, 22, 106, 23),
   (103, 73, 104, 72),
   (78, 60, 79, 59),
   (89, 5, 90, 4)]],
 ['K9a10',
  [(5, 23, 6, 22),
   (13, 50, 14, 51),
   (20, 47, 21, 48),
   (37, 26, 38, 27),
   (21, 5, 22, 4),
   (28, 50, 29, 49),
   (48, 34, 49, 33),
   (38, 53, 39, 0),
   (46, 7, 47, 8),
   (0, 28, 1, 27),
   (12, 29, 13, 30),
   (31, 10, 32, 11),
   (8, 43, 9, 44),
   (52, 39, 53, 40),
   (16, 42, 17, 41),
   (19, 32, 20, 33),
   (25, 44, 26, 45),
   (40, 16, 41, 15),
   (3, 34, 4, 35),
   (1, 36, 2, 37),
   (51, 14, 52, 15),
   (30, 17, 31, 18),
   (11, 19, 12, 18),
   (35, 2, 36, 3),
   (45, 24, 46, 25),
   (42, 9, 43, 10),
   (23, 7, 24, 6)]],
 ['K9a10',
  [(52, 12, 53, 11),
   (51, 76, 52, 77),
   (48, 70, 49, 69),
   (42, 64, 43, 63),
   (43, 2, 44, 3),
   (59, 39, 60, 38),
   (35, 73, 36, 72),
   (57, 30, 58, 31),
   (62, 25, 63, 26),
   (23, 64, 24, 65),
   (75, 12, 76, 13),
   (10, 71, 11, 72),
   (65, 0, 66, 1),
   (67, 18, 68, 19),
   (41, 24, 42, 25),
   (45, 20, 46, 21),
   (9, 17, 10, 16),
   (36, 15, 37, 16),
   (17, 68, 18, 69),
   (74, 53, 75, 54),
   (13, 55, 14, 54),
   (28, 37, 29, 38),
   (22, 2, 23, 1),
   (31, 56, 32, 57),
   (14, 33, 15, 34),
   (55, 32, 56, 33),
   (73, 35, 74, 34),
   (3, 27, 4, 26),
   (5, 40, 6, 41),
   (4, 61, 5, 62),
   (21, 44, 22, 45),
   (66, 48, 67, 47),
   (29, 58, 30, 59),
   (77, 50, 0, 51),
   (19, 46, 20, 47),
   (70, 50, 71, 49),
   (60, 7, 61, 8),
   (39, 6, 40, 7),
   (27, 9, 28, 8)]],
 ['K9a10',
  [(68, 18, 69, 17),
   (22, 89, 23, 90),
   (18, 100, 19, 99),
   (28, 44, 29, 43),
   (48, 30, 49, 29),
   (27, 74, 28, 75),
   (31, 100, 32, 101),
   (36, 5, 37, 6),
   (34, 82, 35, 81),
   (49, 42, 50, 43),
   (57, 46, 58, 47),
   (97, 45, 98, 44),
   (47, 99, 48, 98),
   (50, 76, 51, 75),
   (58, 70, 59, 69),
   (61, 93, 62, 92),
   (65, 81, 66, 80),
   (96, 73, 97, 74),
   (0, 86, 1, 85),
   (67, 4, 68, 5),
   (84, 2, 85, 1),
   (78, 87, 79, 88),
   (79, 65, 80, 64),
   (77, 20, 78, 21),
   (76, 42, 77, 41),
   (39, 25, 40, 24),
   (37, 60, 38, 61),
   (38, 94, 39, 93),
   (94, 12, 95, 11),
   (59, 16, 60, 17),
   (25, 11, 26, 10),
   (53, 12, 54, 13),
   (8, 22, 9, 21),
   (6, 63, 7, 64),
   (7, 89, 8, 88),
   (3, 83, 4, 82),
   (9, 40, 10, 41),
   (45, 56, 46, 57),
   (95, 53, 96, 52),
   (72, 56, 73, 55),
   (13, 54, 14, 55),
   (26, 52, 27, 51),
   (71, 15, 72, 14),
   (66, 35, 67, 36),
   (2, 33, 3, 34),
   (15, 71, 16, 70),
   (19, 31, 20, 30),
   (91, 63, 92, 62),
   (90, 23, 91, 24),
   (83, 33, 84, 32),
   (86, 0, 87, 101)]],
 ['K9a12',
  [(101, 17, 102, 16),
   (95, 83, 96, 82),
   (88, 44, 89, 43),
   (65, 86, 66, 87),
   (30, 85, 31, 86),
   (55, 80, 56, 81),
   (12, 79, 13, 80),
   (64, 30, 65, 29),
   (66, 3, 67, 4),
   (28, 64, 29, 63),
   (61, 42, 62, 43),
   (17, 46, 18, 47),
   (49, 14, 50, 15),
   (6, 13, 7, 14),
   (62, 108, 63, 107),
   (87, 106, 88, 107),
   (18, 104, 19, 103),
   (27, 109, 28, 108),
   (26, 41, 27, 42),
   (25, 75, 26, 74),
   (32, 68, 33, 67),
   (1, 68, 2, 69),
   (0, 83, 1, 84),
   (110, 98, 111, 97),
   (112, 9, 113, 10),
   (111, 52, 112, 53),
   (109, 71, 110, 70),
   (84, 69, 85, 70),
   (73, 25, 74, 24),
   (60, 24, 61, 23),
   (90, 21, 91, 22),
   (45, 22, 46, 23),
   (104, 20, 105, 19),
   (76, 100, 77, 99),
   (78, 7, 79, 8),
   (77, 50, 78, 51),
   (75, 73, 76, 72),
   (4, 94, 5, 93),
   (105, 92, 106, 93),
   (20, 91, 21, 92),
   (44, 90, 45, 89),
   (34, 82, 35, 81),
   (40, 71, 41, 72),
   (38, 52, 39, 51),
   (37, 9, 38, 8),
   (39, 98, 40, 99),
   (48, 57, 49, 58),
   (5, 56, 6, 57),
   (100, 60, 101, 59),
   (15, 59, 16, 58),
   (102, 47, 103, 48),
   (11, 37, 12, 36),
   (94, 33, 95, 34),
   (54, 36, 55, 35),
   (2, 32, 3, 31),
   (53, 114, 54, 115),
   (96, 0, 97, 115),
   (10, 113, 11, 114)]],
 ['K9a29',
  [(35, 10, 36, 11),
   (70, 11, 71, 12),
   (43, 16, 44, 17),
   (36, 54, 37, 53),
   (71, 53, 72, 52),
   (8, 67, 9, 68),
   (56, 70, 57, 69),
   (2, 48, 3, 47),
   (3, 75, 4, 74),
   (83, 18, 0, 19),
   (7, 32, 8, 33),
   (55, 35, 56, 34),
   (27, 48, 28, 49),
   (28, 16, 29, 15),
   (26, 75, 27, 76),
   (30, 41, 31, 42),
   (65, 40, 66, 41),
   (68, 34, 69, 33),
   (61, 46, 62, 47),
   (64, 18, 65, 17),
   (60, 73, 61, 74),
   (44, 63, 45, 64),
   (42, 29, 43, 30),
   (45, 1, 46, 0),
   (13, 6, 14, 7),
   (77, 5, 78, 4),
   (50, 6, 51, 5),
   (82, 40, 83, 39),
   (49, 24, 50, 25),
   (14, 24, 15, 23),
   (76, 25, 77, 26),
   (22, 32, 23, 31),
   (21, 67, 22, 66),
   (19, 38, 20, 39),
   (51, 58, 52, 59),
   (12, 58, 13, 57),
   (78, 59, 79, 60),
   (9, 54, 10, 55),
   (20, 81, 21, 82),
   (62, 1, 63, 2),
   (37, 81, 38, 80),
   (72, 80, 73, 79)]],
 ['K9n2',
  [(16, 29, 17, 30),
   (30, 15, 31, 16),
   (35, 8, 36, 9),
   (1, 34, 2, 35),
   (31, 42, 32, 43),
   (25, 10, 26, 11),
   (28, 38, 29, 37),
   (3, 20, 4, 21),
   (19, 4, 20, 5),
   (0, 10, 1, 9),
   (14, 42, 15, 41),
   (12, 23, 13, 24),
   (43, 26, 0, 27),
   (36, 28, 37, 27),
   (21, 2, 22, 3),
   (24, 34, 25, 33),
   (39, 6, 40, 7),
   (22, 13, 23, 14),
   (11, 32, 12, 33),
   (5, 18, 6, 19),
   (40, 18, 41, 17),
   (7, 38, 8, 39)]],
 ['K9n4',
  [(21, 29, 22, 28),
   (25, 12, 26, 13),
   (6, 27, 7, 28),
   (34, 29, 35, 30),
   (26, 5, 27, 6),
   (24, 31, 25, 32),
   (19, 0, 20, 1),
   (17, 4, 18, 5),
   (16, 11, 17, 12),
   (10, 4, 11, 3),
   (13, 33, 14, 32),
   (2, 10, 3, 9),
   (8, 0, 9, 35),
   (14, 23, 15, 24),
   (7, 20, 8, 21),
   (33, 22, 34, 23),
   (30, 16, 31, 15),
   (1, 18, 2, 19)]]]
In [3]:
exteriors=search_for_friend('K11n34',effort='high',max_number_of_friends=6,verbose=True)
We have choosen the following parameters to search for friends:
random False
random_upper_bound 100
exterior_index 2
try_hard False
isometry_index 2
max_segments 50
upper_bound_dual_curves 250
max_length 4.00000000000000
high_precision False
recursion_limit 50000
upper_bound_geodesics 250
regina_simplify True
regina_retriangulate_index 2
regina_cores_used 1
max_regina_submanifolds 1000
maximal_number_of_Pachner_moves 100
--------------
--------------
We check dual curves with SnapPy and search for a friend.
Number of dual curves: 270
We check all dual curves.
We found a new potential knot exterior: K11n34-0_filled(0,0)
Checking for knot complement: K11n34-0_filled(0,0)
We found a new potential knot exterior: K11n34-1_filled(0,0)
Checking for knot complement: K11n34-1_filled(0,0)
We found a new potential knot exterior: K11n34-16_filled(0,0)
Checking for knot complement: K11n34-16_filled(0,0)
We found a new potential knot exterior: K11n34-24_filled(0,0)
Checking for knot complement: K11n34-24_filled(0,0)
We found a new potential knot exterior: K11n34-26_filled(0,0)
Checking for knot complement: K11n34-26_filled(0,0)
We found a new potential knot exterior: K11n34-28_filled(0,0)
Checking for knot complement: K11n34-28_filled(0,0)
We found a friend: K11n34-28_filled(0,0)
We found a new potential knot exterior: K11n34-32_filled(0,0)
Checking for knot complement: K11n34-32_filled(0,0)
We found a new potential knot exterior: K11n34-49_filled(0,0)
Checking for knot complement: K11n34-49_filled(0,0)
We found a new potential knot exterior: K11n34-51_filled(0,0)
Checking for knot complement: K11n34-51_filled(0,0)
We found a new potential knot exterior: K11n34-53_filled(0,0)
Checking for knot complement: K11n34-53_filled(0,0)
We found a new potential knot exterior: K11n34-55_filled(0,0)
Checking for knot complement: K11n34-55_filled(0,0)
We found a friend: K11n34-55_filled(0,0)
We found a new potential knot exterior: K11n34-56_filled(0,0)
Checking for knot complement: K11n34-56_filled(0,0)
We found a new potential knot exterior: K11n34-64_filled(0,0)
Checking for knot complement: K11n34-64_filled(0,0)
We found a friend: K11n34-64_filled(0,0)
We found a new potential knot exterior: K11n34-72_filled(0,0)
Checking for knot complement: K11n34-72_filled(0,0)
We found a new potential knot exterior: K11n34-86_filled(0,0)
Checking for knot complement: K11n34-86_filled(0,0)
We found a new potential knot exterior: K11n34-87_filled(0,0)
Checking for knot complement: K11n34-87_filled(0,0)
We found a new potential knot exterior: K11n34-88_filled(0,0)
Checking for knot complement: K11n34-88_filled(0,0)
We found a new potential knot exterior: K11n34-91_filled(0,0)
Checking for knot complement: K11n34-91_filled(0,0)
We found a new potential knot exterior: K11n34-94_filled(0,0)
Checking for knot complement: K11n34-94_filled(0,0)
We found a new potential knot exterior: K11n34-97_filled(0,0)
Checking for knot complement: K11n34-97_filled(0,0)
We found a new potential knot exterior: K11n34-100_filled(0,0)
Checking for knot complement: K11n34-100_filled(0,0)
We found a new potential knot exterior: K11n34-101_filled(0,0)
Checking for knot complement: K11n34-101_filled(0,0)
We found a new potential knot exterior: K11n34-103_filled(0,0)
Checking for knot complement: K11n34-103_filled(0,0)
We found a new potential knot exterior: K11n34-104_filled(0,0)
Checking for knot complement: K11n34-104_filled(0,0)
We found a new potential knot exterior: K11n34-105_filled(0,0)
Checking for knot complement: K11n34-105_filled(0,0)
We found a new potential knot exterior: K11n34-107_filled(0,0)
Checking for knot complement: K11n34-107_filled(0,0)
We found a new potential knot exterior: K11n34-109_filled(0,0)
Checking for knot complement: K11n34-109_filled(0,0)
We found a new potential knot exterior: K11n34-111_filled(0,0)
Checking for knot complement: K11n34-111_filled(0,0)
We found a new potential knot exterior: K11n34-120_filled(0,0)
Checking for knot complement: K11n34-120_filled(0,0)
We found a new potential knot exterior: K11n34-122_filled(0,0)
Checking for knot complement: K11n34-122_filled(0,0)
We found a new potential knot exterior: K11n34-124_filled(0,0)
Checking for knot complement: K11n34-124_filled(0,0)
We found a new potential knot exterior: K11n34-126_filled(0,0)
Checking for knot complement: K11n34-126_filled(0,0)
We found a new potential knot exterior: K11n34-127_filled(0,0)
Checking for knot complement: K11n34-127_filled(0,0)
We found a new potential knot exterior: K11n34-146_filled(0,0)
Checking for knot complement: K11n34-146_filled(0,0)
We found a new potential knot exterior: K11n34-156_filled(0,0)
Checking for knot complement: K11n34-156_filled(0,0)
We found a new potential knot exterior: K11n34-159_filled(0,0)
Checking for knot complement: K11n34-159_filled(0,0)
We found a new potential knot exterior: K11n34-161_filled(0,0)
Checking for knot complement: K11n34-161_filled(0,0)
We found a new potential knot exterior: K11n34-170_filled(0,0)
Checking for knot complement: K11n34-170_filled(0,0)
We found a new potential knot exterior: K11n34-173_filled(0,0)
Checking for knot complement: K11n34-173_filled(0,0)
We found a new potential knot exterior: K11n34-178_filled(0,0)
Checking for knot complement: K11n34-178_filled(0,0)
We found a new potential knot exterior: K11n34-190_filled(0,0)
Checking for knot complement: K11n34-190_filled(0,0)
We found a new potential knot exterior: K11n34-196_filled(0,0)
Checking for knot complement: K11n34-196_filled(0,0)
We found a new potential knot exterior: K11n34-200_filled(0,0)
Checking for knot complement: K11n34-200_filled(0,0)
We found a new potential knot exterior: K11n34-207_filled(0,0)
Checking for knot complement: K11n34-207_filled(0,0)
We found a new potential knot exterior: K11n34-208_filled(0,0)
Checking for knot complement: K11n34-208_filled(0,0)
We found a new potential knot exterior: K11n34-211_filled(0,0)
Checking for knot complement: K11n34-211_filled(0,0)
We found a new potential knot exterior: K11n34-212_filled(0,0)
Checking for knot complement: K11n34-212_filled(0,0)
We found a new potential knot exterior: K11n34-213_filled(0,0)
Checking for knot complement: K11n34-213_filled(0,0)
We found a new potential knot exterior: K11n34-219_filled(0,0)
Checking for knot complement: K11n34-219_filled(0,0)
We found a new potential knot exterior: K11n34-222_filled(0,0)
Checking for knot complement: K11n34-222_filled(0,0)
We found a new potential knot exterior: K11n34-232_filled(0,0)
Checking for knot complement: K11n34-232_filled(0,0)
We found a new potential knot exterior: K11n34-233_filled(0,0)
Checking for knot complement: K11n34-233_filled(0,0)
We found a new potential knot exterior: K11n34-239_filled(0,0)
Checking for knot complement: K11n34-239_filled(0,0)
We found a new potential knot exterior: K11n34-243_filled(0,0)
Checking for knot complement: K11n34-243_filled(0,0)
We found a new potential knot exterior: K11n34-248_filled(0,0)
Checking for knot complement: K11n34-248_filled(0,0)
--------------
We check short geodescis with SnapPy and search for a friend.
Number of geodesics in the length spectrum: 212
We check all geodesics.
We found a friend: K11n34_drilled_filled(0,0)
--------------
We drill out knots via Regina.
We check all edges.
Total number of submanifolds found via regina: 829
Number of potential knot exteriors checked: 62
Number of friends found: 4
In [4]:
exteriors
Out[4]:
[K11n34-28_filled(0,0),
 K11n34-55_filled(0,0),
 K11n34-64_filled(0,0),
 K11n34_drilled_filled(0,0)]
In [6]:
print(snappy.Manifold('K11n34').volume(verified=True))
for F in exteriors:
    print(F.volume(verified=True))
11.21911772538?
13.2204588706?
14.3011631097?
14.409961289?
14.301163110?
In [8]:
diagrams=[]
for F in exteriors:
    D=create_diagram(F)
    print(D)
    diagrams.append(D)
[(36, 24, 37, 23), (15, 39, 16, 38), (34, 43, 35, 44), (53, 40, 54, 41), (19, 48, 20, 49), (37, 11, 38, 10), (35, 58, 36, 59), (50, 17, 51, 18), (21, 46, 22, 47), (2, 14, 3, 13), (6, 67, 7, 0), (1, 54, 2, 55), (9, 17, 10, 16), (8, 51, 9, 52), (59, 45, 60, 44), (57, 24, 58, 25), (42, 5, 43, 6), (41, 1, 42, 0), (52, 29, 53, 30), (14, 28, 15, 27), (60, 33, 61, 34), (7, 31, 8, 30), (26, 12, 27, 11), (25, 56, 26, 57), (32, 61, 33, 62), (28, 40, 29, 39), (55, 4, 56, 5), (12, 4, 13, 3), (22, 63, 23, 64), (45, 63, 46, 62), (47, 20, 48, 21), (66, 31, 67, 32), (64, 50, 65, 49), (65, 18, 66, 19)]
[(12, 79, 13, 80), (17, 94, 18, 95), (24, 89, 25, 90), (26, 4, 27, 3), (25, 68, 26, 69), (84, 29, 85, 30), (5, 29, 6, 28), (96, 36, 97, 35), (37, 73, 38, 72), (42, 56, 43, 55), (82, 48, 83, 47), (13, 44, 14, 45), (50, 68, 51, 67), (51, 89, 52, 88), (49, 4, 50, 5), (76, 54, 77, 53), (103, 54, 104, 55), (11, 58, 12, 59), (85, 65, 86, 64), (8, 61, 9, 62), (87, 67, 88, 66), (2, 69, 3, 70), (74, 94, 75, 93), (81, 98, 82, 99), (83, 6, 84, 7), (106, 95, 107, 96), (1, 90, 2, 91), (9, 101, 10, 100), (57, 79, 58, 78), (59, 10, 60, 11), (63, 30, 64, 31), (56, 44, 57, 43), (60, 101, 61, 102), (32, 75, 33, 76), (33, 17, 34, 16), (34, 106, 35, 105), (31, 52, 32, 53), (18, 108, 19, 107), (73, 108, 74, 109), (102, 77, 103, 78), (104, 16, 105, 15), (48, 27, 49, 28), (0, 24, 1, 23), (36, 19, 37, 20), (71, 20, 72, 21), (91, 22, 92, 23), (41, 14, 42, 15), (46, 99, 47, 100), (45, 81, 46, 80), (92, 109, 93, 0), (65, 87, 66, 86), (62, 7, 63, 8), (97, 40, 98, 41), (70, 40, 71, 39), (21, 38, 22, 39)]
[(34, 78, 35, 77), (22, 75, 23, 76), (89, 76, 0, 77), (58, 69, 59, 70), (67, 48, 68, 49), (38, 49, 39, 50), (18, 52, 19, 51), (85, 51, 86, 50), (63, 21, 64, 20), (52, 18, 53, 17), (24, 20, 25, 19), (28, 47, 29, 48), (59, 30, 60, 31), (81, 42, 82, 43), (65, 27, 66, 26), (56, 6, 57, 5), (73, 0, 74, 1), (78, 32, 79, 31), (79, 71, 80, 70), (80, 3, 81, 4), (43, 5, 44, 4), (45, 68, 46, 69), (46, 29, 47, 30), (74, 23, 75, 24), (6, 56, 7, 55), (9, 16, 10, 17), (1, 10, 2, 11), (33, 13, 34, 12), (41, 82, 42, 83), (72, 12, 73, 11), (14, 72, 15, 71), (13, 33, 14, 32), (15, 2, 16, 3), (44, 57, 45, 58), (21, 63, 22, 62), (35, 60, 36, 61), (88, 62, 89, 61), (27, 36, 28, 37), (54, 39, 55, 40), (7, 41, 8, 40), (66, 37, 67, 38), (64, 88, 65, 87), (8, 83, 9, 84), (53, 85, 54, 84), (25, 87, 26, 86)]
[(78, 27, 79, 28), (40, 20, 41, 19), (22, 44, 23, 43), (45, 31, 46, 30), (32, 48, 33, 47), (74, 18, 75, 17), (3, 28, 4, 29), (9, 20, 10, 21), (42, 83, 43, 84), (81, 44, 82, 45), (105, 52, 106, 53), (80, 63, 81, 64), (5, 62, 6, 63), (70, 87, 71, 88), (77, 97, 78, 96), (79, 5, 80, 4), (7, 85, 8, 84), (0, 94, 1, 93), (21, 82, 22, 83), (85, 18, 86, 19), (8, 41, 9, 42), (67, 39, 68, 38), (92, 37, 93, 38), (39, 10, 40, 11), (89, 13, 90, 12), (68, 11, 69, 12), (88, 53, 89, 54), (97, 60, 98, 61), (98, 25, 99, 26), (64, 30, 65, 29), (69, 55, 70, 54), (91, 109, 92, 108), (71, 104, 72, 105), (33, 2, 34, 3), (58, 101, 59, 102), (51, 14, 52, 15), (49, 35, 50, 34), (109, 36, 0, 37), (106, 14, 107, 13), (103, 72, 104, 73), (56, 74, 57, 73), (31, 67, 32, 66), (35, 94, 36, 95), (55, 86, 56, 87), (107, 91, 108, 90), (15, 103, 16, 102), (16, 57, 17, 58), (100, 76, 101, 75), (59, 76, 60, 77), (46, 66, 47, 65), (50, 95, 51, 96), (48, 1, 49, 2), (23, 6, 24, 7), (24, 99, 25, 100), (26, 62, 27, 61)]
In [9]:
for D in diagrams:
    print(len(D))
34
55
45
55
In [13]:
D=snappy.Link([(191, 4, 192, 5), (201, 48, 202, 49), (82, 48, 83, 47), (85, 152, 86, 153), (195, 90, 196, 91), (190, 142, 191, 141), (193, 147, 194, 146), (1, 87, 2, 86), (113, 52, 114, 53), (114, 150, 115, 149), (110, 87, 111, 88), (148, 89, 149, 90), (144, 110, 145, 109), (142, 3, 143, 4), (145, 193, 146, 192), (66, 100, 67, 99), (69, 132, 70, 133), (64, 181, 65, 182), (65, 17, 66, 16), (67, 33, 68, 32), (115, 197, 116, 196), (107, 2, 108, 3), (49, 198, 50, 199), (51, 150, 52, 151), (58, 6, 59, 5), (53, 112, 54, 113), (55, 89, 56, 88), (136, 166, 137, 165), (184, 162, 185, 161), (12, 163, 13, 164), (27, 160, 28, 161), (63, 158, 64, 159), (34, 213, 35, 214), (33, 69, 34, 68), (30, 98, 31, 97), (35, 134, 36, 135), (28, 183, 29, 184), (31, 15, 32, 14), (153, 46, 154, 47), (20, 38, 21, 37), (178, 39, 179, 40), (105, 39, 106, 38), (75, 41, 76, 40), (211, 36, 212, 37), (129, 102, 130, 103), (131, 70, 132, 71), (123, 42, 124, 43), (44, 121, 45, 122), (73, 126, 74, 127), (103, 128, 104, 129), (180, 126, 181, 125), (18, 127, 19, 128), (79, 120, 80, 121), (202, 118, 203, 117), (45, 208, 46, 209), (80, 207, 81, 208), (106, 209, 107, 210), (174, 206, 175, 205), (21, 210, 22, 211), (84, 199, 85, 200), (119, 207, 120, 206), (139, 189, 140, 188), (137, 10, 138, 11), (135, 22, 136, 23), (186, 25, 187, 26), (11, 25, 12, 24), (108, 144, 109, 143), (104, 19, 105, 20), (214, 13, 215, 14), (218, 160, 219, 159), (216, 29, 217, 30), (212, 134, 213, 133), (217, 183, 218, 182), (219, 62, 220, 63), (215, 96, 216, 97), (91, 61, 92, 60), (94, 185, 95, 186), (93, 27, 94, 26), (95, 162, 96, 163), (98, 16, 99, 15), (101, 130, 102, 131), (168, 7, 169, 8), (164, 23, 165, 24), (167, 141, 168, 140), (166, 190, 167, 189), (169, 92, 170, 93), (170, 61, 171, 62), (78, 175, 79, 176), (204, 174, 205, 173), (122, 178, 123, 177), (43, 176, 44, 177), (157, 173, 158, 172), (155, 119, 156, 118), (156, 204, 157, 203), (17, 73, 18, 72), (100, 72, 101, 71), (41, 77, 42, 76), (124, 77, 125, 78), (154, 81, 155, 82), (200, 83, 201, 84), (179, 74, 180, 75), (147, 56, 148, 57), (111, 54, 112, 55), (194, 57, 195, 58), (6, 60, 7, 59), (9, 138, 10, 139), (8, 187, 9, 188), (171, 221, 172, 220), (116, 222, 117, 221), (197, 223, 198, 222), (50, 223, 51, 0), (151, 1, 152, 0)])
D
Out[13]:
<Link: 1 comp; 112 cross>
In [14]:
E=D.exterior()
In [15]:
E.volume(verified=True)
Out[15]:
14.3011631097?
In [16]:
for F in exteriors:
    print(F.is_isometric_to(E))
False
True
False
False
In [ ]: