Example #1
0
def euler_cocycle(tri, angle):
    """
    Given a regina triangulation "tri", with oriented edges, and a
    transverse taut angle structure "angle", returns the associated
    two-cocycle E representing the Euler class E(tri).
    """
    assert is_transverse_taut(tri, angle)
    face_coorientations = is_transverse_taut(tri, angle, return_type = "face_coorientations")
    # E will be a _row_ vector, because it eats column vectors.
    E = []
    # First deal with the truncated faces
    for face in tri.faces(2):  # 2 = dimension
        # First we compute the number of Regina oriented edges that agree with the Regina orientation on face
        AC = 0
        for i in range(3):
            perm = face.faceMapping(1, i)
            # print perm[0], perm[1]
            if perm[1] == ((perm[0] + 1) % 3):  # the edge and face orientations agree so,
                AC = AC + 1
        # print "AC", AC
        # Now we condition on whether or not Regina and angle agree on the (co-)orientation of the face.
        if face_coorientations[face.index()] == 1:
            E.append(AC - 2)
        else:
            E.append(1 - AC)
    # Now deal with the peripheral faces
    for tet in tri.tetrahedra():
        for j in range(4):
            E.append(0)
    return E
Example #2
0
def get_non_triv_sol(tri, angle):
    N = edge_equation_matrix_taut(tri, angle)
    N = Matrix(N)
    non_triv, sol = non_trivial_solution(N, real_bool = False, int_bool = True)
    twiddles = is_transverse_taut(tri, angle, return_type = "face_coorientations")
    sol = [int(a * b) for a, b in zip(sol, twiddles)]
    return sol
Example #3
0
def veering_polynomial(tri,
                       angle,
                       alpha=True,
                       normalisation=True,
                       mode="lower"):
    # set up
    ZH = group_ring(tri, angle, [], alpha=alpha)
    P = ZH.polynomial_ring()
    if verbose > 0:
        print(("angle", angle))

    coorientations = is_transverse_taut(tri,
                                        angle,
                                        return_type="tet_vert_coorientations")

    if mode == "upper":
        coorientations = [[-x for x in coor] for coor in coorientations]

    ET = edges_to_tetrahedra_matrix(tri, angle, coorientations, normalisation,
                                    ZH, P)
    #print(ET)
    if normalisation == True:
        return normalise_poly(ET.determinant(), ZH, P)
    else:
        perm = permutation_tet_top_diagonal(tri, angle, coorientations)
        #print(perm, "sign", sign(perm))
        return sign(perm) * ET.determinant()
Example #4
0
def upper_branched_surface(tri, angle, return_lower=False):
    """Returns the upper branched surface for a veering triangulation"""
    veering_colours = is_veering(tri, angle, return_type="veering_colours")
    tet_vert_coorientations = is_transverse_taut(
        tri, angle, return_type="tet_vert_coorientations")
    assert veering_colours != False and tet_vert_coorientations != False
    branch = []
    for i, a in enumerate(angle):
        assert tet_vert_coorientations[i][0] == tet_vert_coorientations[i][
            a + 1]  ### the other end of the pi edge at 0
        large_edge_num = vert_pair_to_edge_num[(0, a + 1)]
        tiny_edge_num = 5 - large_edge_num
        if (
                tet_vert_coorientations[i][0] == -1
        ) != return_lower:  ### into the tetrahedron through face 0, xor get lower branched surface
            large_edge_num, tiny_edge_num = tiny_edge_num, large_edge_num  # swap
        tiny_edge_colour = veering_colours[tri.tetrahedron(i).edge(
            tiny_edge_num).index()]
        mixed_edge_pair_num = (vert_pair_to_edge_num[(0, a + 1)] +
                               1) % 3  ### can view as an edge num too...
        if veering_colours[tri.tetrahedron(i).edge(
                mixed_edge_pair_num).index()] != tiny_edge_colour:
            mixed_edge_pair_num = (mixed_edge_pair_num +
                                   1) % 3  ### then its the other one
        branch.append(
            branch_num_from_large_edge_and_mixed_edge_pair_num(
                large_edge_num, mixed_edge_pair_num))
    # assert is_branched(tri, branch)
    assert has_non_sing_semiflow(tri, branch)
    return branch
Example #5
0
def perform_all_mutations(tri,
                          angle,
                          weights,
                          tet_vert_coorientations=None,
                          print_stratum=True):
    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    surface, edge_colours = build_surface(tri,
                                          angle,
                                          weights,
                                          return_edge_colours=True)

    if print_stratum == True:
        this_stratum = stratum(tri, angle, weights)
        print('stratum:', this_stratum)

    veering_isoms = veering_symmetry_group(surface, edge_colours)

    if len(veering_isoms) > 1:
        sig = isosig_from_tri_angle(tri, angle)
        for i in range(1, len(veering_isoms)):
            isom = veering_isoms[i]
            tri, angle = isosig_to_tri_angle(sig)
            mutate(tri, angle, weights, isom)
    else:
        print('surface has no veering symmetries')
Example #6
0
def mutate(tri,
           angle,
           weights,
           isom,
           tet_vert_coorientations=None,
           quiet=False):

    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    regluing = surface_isom_to_regluing_pattern(tri, angle, weights, isom,
                                                tet_vert_coorientations)
    #print('regluing data:', regluing)

    # first unglue all faces that need to be unglued, then reglue them via isom
    # can't do both at the same step, because regina goes crazy when you try to glue a face to a face which is already glued somewhere else
    for x in regluing:
        tet_below_top_triangle = tri.tetrahedron(x[0])
        which_face = x[1]
        tet_below_top_triangle.unjoin(which_face)
        #print('unglued face', which_face, 'of tet', tet_below_top_triangle.index())

    for x in regluing:
        tet_below_top_triangle = tri.tetrahedron(x[0])
        which_face = x[1]
        tet_above_image_triangle = tri.tetrahedron(x[2])
        perm = x[3]
        tet_below_top_triangle.join(which_face, tet_above_image_triangle, perm)
        #print('glued face', which_face, 'of tet', tet_below_top_triangle.index(), 'to tet', tet_above_image_triangle.index(), 'via', perm)

    assert tri.isValid()
    assert tri.countBoundaryFacets() == 0

    if quiet == False:
        print('mutant isosig:', tri.isoSig())
        print('taut:', is_taut(tri, angle))
        if is_taut(tri, angle):
            print('transverse taut:', is_transverse_taut(tri, angle))
            print('veering:', is_veering(tri, angle))
        else:
            edge_num = tri.countEdges()
            print('Got', edge_num, 'edges out of', tri.countTetrahedra())
            totals = is_taut(tri, angle, return_totals=True)
            print('Angles:', totals)
Example #7
0
def non_tree_edge_loops_oriented(tri, angle):
    """
    Suppose that T is the (dual) spanning tree.  For every non-tree
    edge e, there is a unique oriented loop in T union e whose
    orientation agrees with the orientation of e (as given by alpha).
    We return this as a list of faces (starting with e) and a list of
    signs (starting with +1).
    """
    loops = non_tree_edge_loops(tri)
    oriented_loops = []
    all_signs = []
    coorientations = is_transverse_taut(tri,
                                        angle,
                                        return_type="tet_vert_coorientations")
    assert coorientations != False
    for loop in loops:
        if len(loop) == 1:
            all_signs.append([1])
        elif len(loop) == 2:
            embeddings = tri.triangle(loop[0]).embeddings()
            tet0, _ = (embed.simplex() for embed in embeddings)
            tet0_faces = [tet0.triangle(i).index() for i in range(4)]
            local_loop0 = tet0_faces.index(loop[0])
            local_loop1 = tet0_faces.index(loop[1])
            tet0_coor = coorientations[tet0.index()]
            if tet0_coor[local_loop0] == tet0_coor[local_loop1]:
                all_signs.append([1, -1])
            else:
                all_signs.append([1, 1])
        else:  # at least three
            # first decide if we need to reverse the loop
            embeddings = tri.triangle(loop[0]).embeddings()
            tet0, tet1 = (embed.simplex() for embed in embeddings)
            tet0_faces = [tet0.triangle(i).index() for i in range(4)]
            local_loop0 = tet0_faces.index(loop[0])
            tet0_coor = coorientations[tet0.index()]
            if tet0_coor[local_loop0] != 1:
                loop.reverse()
                loop = loop[-1:] + loop[:-1]
                tet0, tet1 = tet1, tet0
            # now everything is sensible: that is, tet0 is below face0
            loop_signs = []
            curr_tet = tet0
            for face_ind in loop:
                curr_tet_faces = [
                    curr_tet.triangle(i).index() for i in range(4)
                ]
                local_face_ind = curr_tet_faces.index(face_ind)
                curr_tet_coor = coorientations[curr_tet.index()]
                loop_signs.append(curr_tet_coor[local_face_ind])
                curr_tet = curr_tet.adjacentSimplex(local_face_ind)
            assert loop_signs[0] == 1
            all_signs.append(loop_signs)

        oriented_loops.append(loop)

    return (oriented_loops, all_signs)
Example #8
0
def find_veering_isosigs_from_regina_isosig(regina_isosig, transverse_taut_only = True):
    t = regina.Triangulation3.fromIsoSig(regina_isosig)
    t.orient()
    veer_structs = find_veering_structures(t)
    if transverse_taut_only:
        veer_structs = [struct for struct in veer_structs if is_transverse_taut(t, struct)]
    veering_isosigs = [isosig_from_tri_angle(t, alpha) for alpha in veer_structs]
    veering_isosigs = list(set(veering_isosigs))
    veering_isosigs.sort()
    return veering_isosigs
Example #9
0
def boundary_cycles_from_surface(tri, angle, surface, tet_vert_coorientations = None):
    """ 
    Takes a carried surface. For each cusp of tri, look at the boundary curve
    of the surface on the boundary torus for that cusp. Push it up slightly, record 
    which faces of tri it goes through.
    """

    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(tri, angle, return_type = "tet_vert_coorientations")
    # set up output vectors
    out = []
    for vertex in tri.faces(0):  # 0 is the dimension of the face, so this is cusps
        out.append([0] * tri.countFaces(2))

    edge_sides = edge_side_face_collections(tri, angle, tet_vert_coorientations = tet_vert_coorientations)

    face_coorientations = convert_tetrahedron_coorientations_to_faces(tri, tet_vert_coorientations)

    for f in tri.faces(2):
        weight = surface[f.index()]  # this should be an integer. :)
        for vert_num in range(3):
            cusp_index = f.face(0, vert_num).index()

            sgn = face_coorientations[f.index()]
            trailing_vert_num = (vert_num + sgn) % 3
            trailing_edge = f.face(1, trailing_vert_num) 
            leading_vert_num = (vert_num - sgn) % 3
            leading_edge = f.face(1, leading_vert_num) 
            # these are with respect to right hand rule on surface as viewed from above
            # the faces above us on the trailing edge get -weight, 
            # the faces above us on the leading edge get +weight.

            left, right = edge_sides[trailing_edge.index()]
            pair = (f.index(), trailing_vert_num)
            if pair in left:
                side = left
            else:
                assert pair in right
                side = right
            above = side[side.index(pair) + 1:]
            for (f_ind, vert) in above:
                out[cusp_index][f_ind] -= weight

            left, right = edge_sides[leading_edge.index()]
            pair = (f.index(), leading_vert_num)
            if pair in left:
                side = left
            else:
                assert pair in right
                side = right
            above = side[side.index(pair) + 1:]
            for (f_ind, vert) in above:
                out[cusp_index][f_ind] += weight
    return out
Example #10
0
 def __init__(self, tri, angle, tet_shapes=None):
     self.tri = tri
     self.angle = angle
     assert is_taut(tri, angle)
     self.coorientations = is_transverse_taut(
         tri, angle, return_type="tet_vert_coorientations")
     assert self.coorientations != False
     self.veering_colours = is_veering(tri,
                                       angle,
                                       return_type="veering_colours")
     assert self.veering_colours != False
     self.tet_types = is_veering(tri, angle, return_type="tet_types")
     self.tet_shapes = tet_shapes
Example #11
0
def triangle_is_red(tri, angle, face_index, tet_vert_coorientations=None):

    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    edge_index_where_uppermost = where_faces_are_uppermost(
        tri, angle, tet_vert_coorientations
    )[face_index]  #face has the same colour as the edge where it is uppermost

    colour = is_veering(
        tri, angle, return_type='veering_colours')[edge_index_where_uppermost]

    return (colour == 'red')
Example #12
0
def verts_of_large_small_same_coloured_edges_in_embeds(
        tri, angle, face_index, tet_vert_coorientations=None):
    """
    returns [vertices of large edge, vertices of small edge of the same colour] for top embedding and bottom embedding of a face
    """
    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    top_embed, bottom_embed = top_bottom_embeddings_of_faces(
        tri, angle, tet_vert_coorientations
    )[0][face_index], top_bottom_embeddings_of_faces(
        tri, angle, tet_vert_coorientations)[1][face_index]

    tet_below = top_embed.simplex()
    tet_above = bottom_embed.simplex()
    tet_below_coor = tet_vert_coorientations[tet_below.index()]
    tet_above_coor = tet_vert_coorientations[tet_above.index()]
    verts_of_top_diagonal_of_tet_below = [
        i for i in range(4) if tet_below_coor[i] == -1
    ]  # this edge is small, of the same colour as large
    verts_of_bottom_diagonal_of_tet_above = [
        i for i in range(4) if tet_above_coor[i] == +1
    ]  # this edge is large
    #print('small edge in top embed', verts_of_top_diagonal_of_tet_below)
    #print('large edge in bottom embed', verts_of_bottom_diagonal_of_tet_above)

    vertex_correspondence = vertex_correspondence_between_embeds(
        bottom_embed, top_embed)
    #print('bottom top vertex correspondence', vertex_correspondence)
    verts_of_large_edge_of_top_embed = []
    for x in vertex_correspondence:
        if x[0] == verts_of_bottom_diagonal_of_tet_above[0] or x[
                0] == verts_of_bottom_diagonal_of_tet_above[1]:
            verts_of_large_edge_of_top_embed.append(x[1])
    verts_of_other_edge_of_same_colour_in_bottom_embed = []
    for x in vertex_correspondence:
        if x[1] == verts_of_top_diagonal_of_tet_below[0] or x[
                1] == verts_of_top_diagonal_of_tet_below[1]:
            verts_of_other_edge_of_same_colour_in_bottom_embed.append(x[0])

    #print('large edge in top embed', verts_of_large_edge_of_top_embed)
    #print('small edge in bottom embed', verts_of_other_edge_of_same_colour_in_bottom_embed)

    return [
        verts_of_large_edge_of_top_embed, verts_of_top_diagonal_of_tet_below
    ], [
        verts_of_bottom_diagonal_of_tet_above,
        verts_of_other_edge_of_same_colour_in_bottom_embed
    ]
Example #13
0
def pairing_of_faces_across_an_edge(tri,
                                    angle,
                                    weights,
                                    edge_index,
                                    tet_vert_coorientations=None):
    """
    given a solution to the system of branch equations gives a pairing of faces across an edge (together with the index of the edge in that face)
    """

    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    edge_sides = edge_side_face_collections(
        tri, angle,
        tet_vert_coorientations=tet_vert_coorientations)[edge_index]

    side0 = edge_sides[0]
    for i in range(len(side0)):
        face_index = side0[i][0]
        weight = weights[face_index]
        side0[i] = [
            side0[i], weight
        ]  #first replace side_collections into weighted_side_collections

    sum_of_weights0 = sum(weight for [_, weight] in side0)

    side0_nonzero_weights = []
    for x in side0:
        for k in range(x[1]):
            side0_nonzero_weights.append(x[0])

    side1 = edge_sides[1]
    for i in range(len(side1)):
        face_index = side1[i][0]
        weight = weights[face_index]
        side1[i] = [side1[i], weight]

    sum_of_weights1 = sum(weight for [_, weight] in side1)
    assert sum_of_weights0 == sum_of_weights1

    side1_nonzero_weights = []
    for x in side1:
        for k in range(x[1]):
            side1_nonzero_weights.append(x[0])

    return ([side0_nonzero_weights, side1_nonzero_weights])
Example #14
0
def taut_cone_homological_dim(tri, angle):
    # find the dimension of the projection of the taut cone into
    # homology

    # boundaries of tets
    bdys = zeroth_coboundary(tri)
    bdys = matrix_transpose(bdys)
    rays = taut_rays(tri, angle)
    # but these are all 'upwards', so we need to fix the
    # co-orientations
    coorient = is_transverse_taut(tri, angle, return_type = "face_coorientations")
    rays = [[int(a * b) for a, b in zip(coorient, ray)] for ray in rays]

    # now work in the space of two-chains
    Rays = IntegerLattice(rays + bdys)
    Bdys = Matrix(bdys)
    Cobs = Bdys.transpose()
    Anns = Cobs.kernel()
    return Rays.intersection(Anns).dimension()
Example #15
0
def appears_twice_on_the_same_side(tri,
                                   angle,
                                   face_index,
                                   edge_index,
                                   tet_vert_coorientations=None):
    """
    tells if a face is attached twice on the same side of an edge (if so, then lowermost and uppermost)
    """

    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    edge_sides = edge_side_face_collections(
        tri, angle,
        tet_vert_coorientations=tet_vert_coorientations)[edge_index]
    side0 = edge_sides[0]
    side1 = edge_sides[1]

    return side0[0][0] == side0[-1][0] and side0[-1][0] == face_index or side1[
        0][0] == side1[-1][0] and side1[-1][0] == face_index
Example #16
0
def is_uppermost(tri,
                 angle,
                 face_index,
                 edge_index_in_face,
                 edge_index,
                 tet_vert_coorientations=None):
    """
    tells if (face_index, edge_index_in_face) is uppermost for that edge
    """

    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    edge_sides = edge_side_face_collections(
        tri, angle,
        tet_vert_coorientations=tet_vert_coorientations)[edge_index]
    side0 = edge_sides[0]
    side1 = edge_sides[1]

    return (side0[-1] == (face_index, edge_index_in_face)
            or side1[-1] == (face_index, edge_index_in_face))
Example #17
0
def where_faces_are_uppermost(tri, angle, tet_vert_coorientations=None):
    """
    returns a list whose ith elements is the index of the edge where the ith face is uppermost
    """
    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    n = tri.countTetrahedra()

    where_uppermost = [None] * 2 * n
    sides = edge_side_face_collections(tri, angle, tet_vert_coorientations)
    for edge in tri.edges():
        uppermost0_index = sides[edge.index()][0][-1][0]
        where_uppermost[uppermost0_index] = edge.index()
        uppermost1_index = sides[edge.index()][1][-1][0]
        where_uppermost[uppermost1_index] = edge.index()

    for x in where_uppermost:
        assert x != None

    return where_uppermost
Example #18
0
def is_fibered(snappy_name, tries=1000, with_data=False):
    """
    Given an snappy_name, tries to find a layered transverse taut
    triangulation for the manifold via random search.
    """
    sigs = get_many_sigs(snappy_name, tries)
    for sig in sigs:
        T = regina.Triangulation3(sig)
        T.orient()
        angle_strs = list(regina.AngleStructures.enumerate(T, True))
        angle_strs = [
            taut_regina_angle_struct_to_taut_struct(angle_str)
            for angle_str in angle_strs
        ]
        for angle in angle_strs:
            # we are not interested in semi-fibered manifolds so:
            if is_transverse_taut(T, angle) and is_layered(T, angle):
                if with_data:
                    return (True, T.isoSig(), angle)
                return True

    return False
Example #19
0
def top_bottom_embeddings_of_faces(tri, angle, tet_vert_coorientations=None):
    """
    returns two lists: one whose ith entry is the top embedding of face i, another whose ith entry is the bottom embedding of face i
    (top embedding = embedding as a top face)
    """

    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    n = tri.countTetrahedra()

    top_embeddings = [None] * 2 * n
    bottom_embeddings = [None] * 2 * n

    for face in tri.triangles():
        embed0 = face.embedding(0)
        embed1 = face.embedding(1)
        tet0_index = embed0.simplex().index()
        tet1_index = embed1.simplex().index()
        index_of_face_in_tet0 = embed0.vertices()[3]
        index_of_face_in_tet1 = embed1.vertices()[3]
        if tet_vert_coorientations[tet0_index][
                index_of_face_in_tet0] == 1:  # coorientation points out of tet0, i.e. tet0 is below f
            top_embedding = embed0
            bottom_embedding = embed1
        else:
            top_embedding = embed1
            bottom_embedding = embed0
        top_embeddings[face.index()] = top_embedding
        bottom_embeddings[face.index()] = bottom_embedding

    for i in range(2 * n):
        assert top_embeddings[i] != None and bottom_embeddings[i] != None

    return top_embeddings, bottom_embeddings
Example #20
0
def coboundary(tri, angle):
    """
    Given a triangulation "tri" (T), with oriented edges, and a
    transverse taut angle structure "angle", returns the co-boundary
    operator delta^1 \from C^1(T', ZZ) \to C^2(T', ZZ), as a matrix,
    for the truncated triangulation T'.  Note that, strictly speaking,
    we don't need to use "angle" for this, but we use it to determine
    orientation on faces for the Euler class, so we might as well use
    it again here.
    """
    # \delta^1 takes row vectors (functions on edges) and spits out
    # row vectors (functions on faces).  So, if c is a one-cochain
    # then c \cdot \delta is a two-cochain.
    delta = []
    assert is_transverse_taut(tri, angle)
    tet_vert_coorientations = is_transverse_taut(tri, angle, return_type = "tet_vert_coorientations")
    face_coorientations = is_transverse_taut(tri, angle, return_type = "face_coorientations")

    for edge in tri.edges():
        # A row for every truncated edge
        row = []
        for face in tri.triangles():
            # A row entry for every truncated face
            count = 0
            for i in range(3):
                if face.edge(i) == edge:
                    perm = face.faceMapping(1, i)
                    if perm[1] == ((perm[0] + 1) % 3):
                        # the edge and face orientations agree so,
                        count += 1
                    else:
                        count -= 1
            row.append(count * face_coorientations[face.index()])
            # +1 if face is to the left of the edge, -1 if face is to
            # the right of the edge, using Regina's edge orientation
            # when viewed from above (using the transverse taut notion
            # of up)

            #        ,'|
            #      ,'  |
            #    ,'    |
            #  ,'  CCW |  gets a +1
            #  `.      ^
            #    `.    |
            #      `.  |
            #        `.|

        for tet in tri.simplices():
            for i in range(4):
                row.append(0)
        delta.append(row)

    for face in tri.triangles():
        face_embeddings = []
        for j in range(2):
            face_embeddings.append( face.embedding(j) )

        for i in range(3):  # vertices of the face
            # A row for every peripheral edge
            row = []

            for face2 in tri.triangles():
                # A row entry for every truncated face
                if face2 == face:
                    row.append(1)
                else:
                    row.append(0)

            for tet in tri.simplices():
                for k in range(4):
                    # A row entry for every peripheral face
                    count = 0
                    for j in range(2):
                        if (tet == face_embeddings[j].simplex()) and (face_embeddings[j].vertices()[i] == k):
                            # the tetrahedron is on the jth side of the
                            # face and the ith vertex of face is the kth
                            # vertex of tet
                            face_num_in_tet = face_embeddings[j].vertices()[3]
                            count -= tet_vert_coorientations[tet.index()][face_num_in_tet]
                            # tet_vert_coorientations is +1 if
                            # coorientation on face points out of the
                            # tetrahedron, and we want count += 1 if
                            # the peripheral face is above the
                            # peripheral edge
                    row.append(count)
            delta.append(row)
    return delta
Example #21
0
def top_triangles_to_surface_triangles(tri,
                                       angle,
                                       weights,
                                       tet_vert_coorientations=None):
    """
    Gives a map from the top triangles of the cut 3-manifold to the surface triangles (works only for surface built using build_surface!).
    If weight >  1 then the map sends a triangle f of the 3D-triangulation to the triangle of the surface corresponding to the "lowermost" (first) copy of f in the surface.
    The output format is a list of length 2*num_tet, whose entries are either None (if the face is not unglued in the cut manifold) or a list [tet_num, [vertices of tet], triangle_num, [vertices of tri]]
    """

    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    n = tri.countTetrahedra()

    top_embeddings, _ = top_bottom_embeddings_of_faces(
        tri, angle, tet_vert_coorientations)
    #print('top embeddings', top_embeddings)

    for i in range(2 * n):
        if weights[i] > 0:  # the ith face of the 3D-triangulation is unglued
            which_surface_triangle = sum(
                weights[:i]
            )  # the index of the surface triangle corresponding to the "lowermost" copy of face i
            top_embed = top_embeddings[i]
            [verts_of_large_edge, verts_of_small_edge_of_same_colour
             ] = verts_of_large_small_same_coloured_edges_in_embeds(
                 tri, angle, i, tet_vert_coorientations)[0]
            common_vertex = [
                x for x in verts_of_large_edge
                if x in verts_of_small_edge_of_same_colour
            ][0]
            #print('verts of large', verts_of_large_edge)
            #print('verts_of_small_edge_of_same_colour', verts_of_small_edge_of_same_colour)
            #print('common vertex', common_vertex)
            #verts_of_large_edge_copy = verts_of_large_edge.copy()
            verts_of_large_edge.remove(common_vertex)
            other_vertex_of_large = verts_of_large_edge[0]
            #print('other_vertex_of_large', other_vertex_of_large)
            verts_of_small_edge_of_same_colour.remove(common_vertex)
            other_vertex_of_small = verts_of_small_edge_of_same_colour[0]
            if triangle_is_red(tri, angle, i, tet_vert_coorientations):
                # mapping common_vertex --> 0, other_vertex_of_large --> 1, other_vertex_of_small --> 2
                vertex_mapping = [
                    top_embed.simplex().index(),
                    [
                        common_vertex, other_vertex_of_large,
                        other_vertex_of_small
                    ], which_surface_triangle, [0, 1, 2]
                ]
            else:
                # mapping common_vertex --> 1, other_vertex_of_large --> 0, other_vertex_of_small --> 2
                vertex_mapping = [
                    top_embed.simplex().index(),
                    [
                        other_vertex_of_large, common_vertex,
                        other_vertex_of_small
                    ], which_surface_triangle, [0, 1, 2]
                ]
            #top_embeddings[i] = [top_embeddings[i]]
            #top_embeddings[i].append(vertex_mapping)
            top_embeddings[i] = vertex_mapping
        else:
            top_embeddings[
                i] = None  #so that it is clear that this face is not unglued in the cut manifold

    return top_embeddings
Example #22
0
def build_surface(tri,
                  angle,
                  weights,
                  tet_vert_coorientations=None,
                  return_edge_colours=False):

    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    surface = regina.Triangulation2()
    n = tri.countTetrahedra()

    for i in range(2 * n):
        for j in range(weights[i]):
            surface.newTriangle()

    colours = is_veering(tri, angle, return_type='veering_colours')

    edge_colours_pairs = []  # red, blue or black (dual to large branches)

    for edge in tri.edges():
        pairings = pairing_of_faces_across_an_edge(tri, angle, weights,
                                                   edge.index(),
                                                   tet_vert_coorientations)
        height = len(pairings[0])
        #print('height', height)

        #now we get (face_index, index of e in the face) so have to pick the first one
        face_indices0 = [pairings[0][i][0] for i in range(height)]
        face_indices1 = [pairings[1][i][0] for i in range(height)]

        for i in range(height):
            #face0_index = pairings[0][i][0] #now we get (face_index, index of e in the face) so have to pick the first one
            face0_index = face_indices0[i]
            edge_index_in_face0 = pairings[0][i][1]
            #face1_index = pairings[1][i][0]
            face1_index = face_indices1[i]
            edge_index_in_face1 = pairings[1][i][1]

            which_copy0 = face_indices0[:i].count(face0_index)
            # check if not overcounting (if a face is both uppermost and lowermost on the same side)
            if is_uppermost(tri, angle, face0_index, edge_index_in_face0,
                            edge.index(), tet_vert_coorientations
                            ) and appears_twice_on_the_same_side(
                                tri, angle, face0_index, edge.index(),
                                tet_vert_coorientations):
                which_copy0 = which_copy0 - weights[face0_index]

            which_copy1 = face_indices1[:i].count(face1_index)
            if is_uppermost(tri, angle, face1_index, edge_index_in_face1,
                            edge.index(), tet_vert_coorientations
                            ) and appears_twice_on_the_same_side(
                                tri, angle, face1_index, edge.index(),
                                tet_vert_coorientations):
                which_copy1 = which_copy1 - weights[face1_index]

            #which_copy0 = face_indices0[:i].count(face0_index)
            #which_copy1 = face_indices1[:i].count(face1_index)

            which_triangle0 = sum(weights[:face0_index]) + which_copy0
            which_triangle1 = sum(weights[:face1_index]) + which_copy1

            #print('which triangle 0', which_triangle0)
            #print('which triangle 1', which_triangle1)

            if colours[edge.index(
            )] == 'red':  # gluing triangles across a red edge
                if is_uppermost(tri, angle, face0_index, edge_index_in_face0,
                                edge.index(), tet_vert_coorientations):
                    if is_uppermost(tri, angle,
                                    face1_index, edge_index_in_face1,
                                    edge.index(), tet_vert_coorientations):
                        surface.triangle(which_triangle0).join(
                            2, surface.triangle(which_triangle1),
                            regina.Perm3(1, 0, 2))
                        #first we append edge_colours with tuples [face_index, edge_index_in_face, colour]; after finishing the triangulation we will change it into a tuple of colours ordered by indices
                        edge_colours_pairs.append(
                            [which_triangle0, 2, 'black'])
                    else:  # middle and lowermost have the same permutation
                        surface.triangle(which_triangle0).join(
                            2, surface.triangle(which_triangle1),
                            regina.Perm3(0, 2, 1))
                        edge_colours_pairs.append([which_triangle0, 2, 'red'])
                else:  # middle or lowermost
                    if is_uppermost(tri, angle,
                                    face1_index, edge_index_in_face1,
                                    edge.index(), tet_vert_coorientations):
                        surface.triangle(which_triangle0).join(
                            1, surface.triangle(which_triangle1),
                            regina.Perm3(0, 2, 1))
                        edge_colours_pairs.append([which_triangle0, 1, 'red'])
                    else:
                        surface.triangle(which_triangle0).join(
                            1, surface.triangle(which_triangle1),
                            regina.Perm3(2, 1, 0))
                        edge_colours_pairs.append([which_triangle0, 1, 'red'])
            else:  # gluing triangles across a blue edge
                if is_uppermost(tri, angle, face0_index, edge_index_in_face0,
                                edge.index(), tet_vert_coorientations):
                    if is_uppermost(tri, angle,
                                    face1_index, edge_index_in_face1,
                                    edge.index(), tet_vert_coorientations):
                        surface.triangle(which_triangle0).join(
                            2, surface.triangle(which_triangle1),
                            regina.Perm3(1, 0, 2))
                        edge_colours_pairs.append(
                            [which_triangle0, 2, 'black'])
                    else:  # middle and lowermost have the same permutation
                        surface.triangle(which_triangle0).join(
                            2, surface.triangle(which_triangle1),
                            regina.Perm3(2, 1, 0))
                        edge_colours_pairs.append([which_triangle0, 2, 'blue'])
                else:  # middle or lowermost
                    if is_uppermost(tri, angle,
                                    face1_index, edge_index_in_face1,
                                    edge.index(), tet_vert_coorientations):
                        surface.triangle(which_triangle0).join(
                            0, surface.triangle(which_triangle1),
                            regina.Perm3(2, 1, 0))
                        edge_colours_pairs.append([which_triangle0, 0, 'blue'])
                    else:
                        surface.triangle(which_triangle0).join(
                            0, surface.triangle(which_triangle1),
                            regina.Perm3(0, 2, 1))
                        edge_colours_pairs.append([which_triangle0, 0, 'blue'])

    assert surface.isClosed()

    #print (edge_colours_pairs)

    if return_edge_colours == True:
        k = surface.countEdges()
        edge_colours = [None] * k
        for x in edge_colours_pairs:
            edge_index = surface.triangle(x[0]).edge(x[1]).index()
            edge_colours[edge_index] = x[2]
        return surface, edge_colours

    return surface
Example #23
0
def surface_triangles_to_bottom_triangles(tri,
                                          angle,
                                          weights,
                                          tet_vert_coorientations=None):
    """
    Gives a map from (some) surface triangles to bottom triangles of the cut 3-manifold.
    If weight >  1 then only the uppermost (last) copy of the 3-manifold triangle in the surface has a 3-manifold triangle assigned.
    The output format is a list of length 2*num_tet, whose entries are either None (if the face is not unglued in the cut manifold) or a list [triangle_num, [vertices of tri], tet_num, [vertices of tet]]
    """

    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    n = tri.countTetrahedra()

    _, bottom_embeddings = top_bottom_embeddings_of_faces(
        tri, angle, tet_vert_coorientations)

    for i in range(2 * n):
        if weights[i] > 0:  # the ith face of the 3D-triangulation is unglued
            which_surface_triangle = sum(
                weights[:i + 1]
            ) - 1  # the "uppermost" copy of face i which appears in the surface
            bottom_embed = bottom_embeddings[i]
            [verts_of_large_edge, verts_of_small_edge_of_same_colour
             ] = verts_of_large_small_same_coloured_edges_in_embeds(
                 tri, angle, i, tet_vert_coorientations)[1]
            common_vertex = [
                x for x in verts_of_large_edge
                if x in verts_of_small_edge_of_same_colour
            ][0]
            #print('verts of large', verts_of_large_edge)
            #print('verts_of_small_edge_of_same_colour', verts_of_small_edge_of_same_colour)
            #print('common vertex', common_vertex)
            verts_of_large_edge.remove(common_vertex)
            other_vertex_of_large = verts_of_large_edge[0]
            #print('other_vertex_of_large', other_vertex_of_large)
            verts_of_small_edge_of_same_colour.remove(common_vertex)
            other_vertex_of_small = verts_of_small_edge_of_same_colour[0]
            if triangle_is_red(tri, angle, i, tet_vert_coorientations):
                #mapping common_vertex --> 0, other_vertex_of_large --> 1, other_vertex_of_small --> 2
                vertex_mapping = [
                    which_surface_triangle, [0, 1, 2],
                    bottom_embed.simplex().index(),
                    [
                        common_vertex, other_vertex_of_large,
                        other_vertex_of_small
                    ]
                ]
            else:
                #mapping common_vertex --> 1, other_vertex_of_large --> 0, other_vertex_of_small --> 2
                vertex_mapping = [
                    which_surface_triangle, [0, 1, 2],
                    bottom_embed.simplex().index(),
                    [
                        other_vertex_of_large, common_vertex,
                        other_vertex_of_small
                    ]
                ]
            #bottom_embeddings[i] = [bottom_embeddings[i]]
            #bottom_embeddings[i].append(vertex_mapping)
            bottom_embeddings[i] = vertex_mapping
        else:
            bottom_embeddings[
                i] = None  #so that it is clear that this face is not unglued in the cut manifold

    return bottom_embeddings
Example #24
0
def surface_isom_to_regluing_pattern(tri,
                                     angle,
                                     weights,
                                     isom,
                                     tet_vert_coorientations=None):
    """
    Translation between a combinatorial isomorphism of a carried surface and the associated mutation pattern.
    """
    #isom must be a combinatorial isomorphism of a surface build using build_surface

    # 1. Get the top embeds to surface triangles map (if weights > 1 then the lowermost copy - the one which has a tet below, and not a 'prism').
    # 2. Find images of triangles and permutations on vertices under the isomorphism.
    # 3. For every simpImage check if it is in the list obtained via surface_triangles_to_bottom triangles. If so, then it has a tet above (and not a prism), so the regluing pattern is
    # top embed --> surface triangle (lowermost over top embed) --isom--> surface triangle (uppermost over some tet) --> bottom face of the tet above
    # Otherwise, we look at the copy of the 3D-triangle in the surface which is above this surface triangle, apply isom again etc.

    if tet_vert_coorientations == None:
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")

    top_tri_to_surface_tri = top_triangles_to_surface_triangles(
        tri, angle, weights, tet_vert_coorientations)
    surface_tri_to_bottom_tri = surface_triangles_to_bottom_triangles(
        tri, angle, weights, tet_vert_coorientations)

    k = len(surface_tri_to_bottom_tri)
    auxiliary = [None] * k
    for i in range(k):
        if surface_tri_to_bottom_tri[i] != None:
            auxiliary[i] = surface_tri_to_bottom_tri[i][0]
    # auxiliary[k] is either None or an index of a surface triangle which has a tet above -- I want to keep Nones so that later I can find the index of the bottom triangle in surface_tri_to_bottom_tri by value

    regluing = []

    for i in range(len(top_tri_to_surface_tri)):
        if top_tri_to_surface_tri[
                i] != None:  # this triangle is unglued in the cut manifold
            #print('top triangle to surface triangle', top_tri_to_surface_tri[i])
            surface_tri_index = top_tri_to_surface_tri[i][2]
            tri_image = isom.simpImage(surface_tri_index)
            isom_perm = isom.facetPerm(surface_tri_index)
            #print('first tri image and perm', tri_image, isom_perm)
            if tri_image in auxiliary:
                index_in_surface_to_bottom_tri = auxiliary.index(tri_image)
                #print('surface triangle', tri_image, 'has a tet above')
            while tri_image not in auxiliary:  #look at further images
                #print('tri_image does not have a tet above')
                triangle_above = tri_image + 1
                tri_image = isom.simpImage(
                    triangle_above)  #look at the image of the upper copy
                isom_perm = isom.facetPerm(triangle_above) * isom_perm
                #print('next tri image and perm', tri_image, isom_perm)
                if tri_image in auxiliary:
                    index_in_surface_to_bottom_tri = auxiliary.index(tri_image)
                    #print('surface triangle', tri_image, 'has a tet above')
            top_to_surface_perm = vertex_correspondence_to_perm4(
                top_tri_to_surface_tri[i][1], top_tri_to_surface_tri[i][3])
            #print('top tri to surface tri perm', top_to_surface_perm)
            isom_perm4 = regina.Perm4(isom_perm[0], isom_perm[1], isom_perm[2],
                                      3)
            #print('4perm associated to isom', isom_perm4)
            bottom_to_surface_perm = vertex_correspondence_to_perm4(
                surface_tri_to_bottom_tri[index_in_surface_to_bottom_tri][3],
                surface_tri_to_bottom_tri[index_in_surface_to_bottom_tri][1])
            #print('bottom tri to surface tri perm', bottom_to_surface_perm)
            surface_to_bottom_perm = bottom_to_surface_perm.inverse()
            #print('surface to bottom perm', surface_to_bottom_perm)
            perm = surface_to_bottom_perm * isom_perm4 * top_to_surface_perm
            #print('gluing perm', perm)

            tet_below_top_embed = top_tri_to_surface_tri[i][0]
            which_face = face_num_in_tet(top_tri_to_surface_tri[i][1])
            tet_above_image = surface_tri_to_bottom_tri[
                index_in_surface_to_bottom_tri][2]

            regluing.append(
                [tet_below_top_embed, which_face, tet_above_image, perm])

    return regluing
Example #25
0
def drill(tri,
          loop,
          angle=None,
          branch=None,
          sig=None):  # sig just for diagnostics
    """
    Returns the new cusp formed by drilling
    """
    if angle != None:
        face_coorientations = is_transverse_taut(
            tri, angle, return_type="face_coorientations")
        assert face_coorientations != False
        tet_vert_coorientations = is_transverse_taut(
            tri, angle, return_type="tet_vert_coorientations")
        assert tet_vert_coorientations != False

    original_tri = regina.Triangulation3(tri)

    original_countTetrahedra = tri.countTetrahedra()
    original_countBoundaryComponents = tri.countBoundaryComponents()
    ### add new tetrahedra
    new_0_tets = []
    new_1_tets = []  ## both relative to regina's two embeddings for the face
    for i in range(len(loop)):
        new_0_tets.append(tri.newTetrahedron())
        new_1_tets.append(tri.newTetrahedron())

    ### we will glue tetrahedra together with a numbering that is convenient but
    ### unfortunately not oriented. We will orient later.

    #           1  pivot
    #          /|\
    #         / | \
    #        / ,3. \
    #       /,'   `.\
    #      0---------2 leading
    # trailing

    for i in range(len(loop)):
        new_0_tets[i].join(1, new_1_tets[i], regina.Perm4(0, 1, 2, 3))

    ### now glue along the loop path, need to worry about regina's embeddings for neighbouring triangles

    loop_face_tets0 = []
    loop_face_vertices0 = []
    loop_face_tets1 = []
    loop_face_vertices1 = [
    ]  ### need to store these because they cannot be recomputed once we start ungluing faces

    for i in range(len(loop)):
        # print('collect info: i', i)
        face_data = loop[i]
        face_index = face_data[0]
        vert_nums = face_data[1]
        face = tri.triangles()[face_index]
        face_embed0 = face.embedding(0)
        face_tet = face_embed0.simplex()
        face_vertices = face_embed0.vertices()
        face_opposite_vert = face_vertices[3]
        face_other_non_edge_vert = face_vertices[
            vert_nums[0]]  ## opposite trailing vertex

        face_data_next = loop[(i + 1) % len(loop)]
        face_index_next = face_data_next[0]
        vert_nums_next = face_data_next[1]
        face_next = tri.triangles()[face_index_next]
        face_next_embed0 = face_next.embedding(0)
        face_next_tet = face_next_embed0.simplex()
        face_next_vertices = face_next_embed0.vertices()
        face_next_opposite_vert = face_next_vertices[3]
        face_next_other_non_edge_vert = face_next_vertices[
            vert_nums_next[2]]  ## opposite leading vertex

        ### things to store for later

        loop_face_tets0.append(face_tet)  # store for later
        loop_face_vertices0.append(face_vertices)  #store for later
        face_embed1 = face.embedding(1)
        loop_face_tets1.append(face_embed1.simplex())
        loop_face_vertices1.append(face_embed1.vertices())

        edge = face.edge(vert_nums[0])  ## opposite trailing vertex
        # print('edge index', edge.index())
        assert edge == face_next.edge(
            vert_nums_next[2])  ## opposite leading vertex

        edgemapping = face.faceMapping(1, vert_nums[0])
        next_edgemapping = face_next.faceMapping(1, vert_nums_next[2])
        face_gluing_regina_numbering = next_edgemapping * (
            edgemapping.inverse()
        )  ### maps vertices 0,1,2 on face to corresponding vertices on face_next
        assert face_gluing_regina_numbering[3] == 3
        face_gluing_regina_numbering = regina.Perm3(
            face_gluing_regina_numbering[0], face_gluing_regina_numbering[1],
            face_gluing_regina_numbering[2])
        assert face_gluing_regina_numbering[vert_nums[0]] == vert_nums_next[2]
        face_gluing = vert_nums_next.inverse(
        ) * face_gluing_regina_numbering * vert_nums
        assert face_gluing[0] == 2

        signs = []
        edge_embeddings = edge.embeddings()
        for embed in edge_embeddings:
            if embed.simplex() == face_tet:
                if set([embed.vertices()[2],
                        embed.vertices()[3]]) == set(
                            [face_opposite_vert, face_other_non_edge_vert]):
                    # print('embed data face_tet', embed.simplex().index(), embed.vertices())
                    # print('embed edge vert nums', embed.vertices()[0], embed.vertices()[1])
                    signs.append(face_opposite_vert == embed.vertices()[2])
            if embed.simplex() == face_next_tet:
                if set([embed.vertices()[2],
                        embed.vertices()[3]]) == set([
                            face_next_opposite_vert,
                            face_next_other_non_edge_vert
                        ]):
                    # print('embed data face_next_tet', embed.simplex().index(), embed.vertices())
                    # print('embed edge vert nums', embed.vertices()[0], embed.vertices()[1])
                    signs.append(
                        face_next_opposite_vert == embed.vertices()[2])
        # print('signs', signs)
        assert len(signs) == 2
        if signs[0] == signs[
                1]:  ### coorientations are same around the edge (not a transverse taut coorientation!)
            new_0_tets[i].join(
                0, new_1_tets[(i + 1) % len(loop)],
                regina.Perm4(2, face_gluing[1], face_gluing[2], 3))
            new_1_tets[i].join(
                0, new_0_tets[(i + 1) % len(loop)],
                regina.Perm4(2, face_gluing[1], face_gluing[2], 3))
        else:
            new_0_tets[i].join(
                0, new_0_tets[(i + 1) % len(loop)],
                regina.Perm4(2, face_gluing[1], face_gluing[2], 3))
            new_1_tets[i].join(
                0, new_1_tets[(i + 1) % len(loop)],
                regina.Perm4(2, face_gluing[1], face_gluing[2], 3))

    ### now unglue tri along the loop and glue in the new tetrahedra

    for i in range(len(loop)):
        # print('modify triangulation: i', i)
        vert_nums = loop[i][1]

        face_tet0 = loop_face_tets0[i]
        face_vertices0 = loop_face_vertices0[i]
        face_tet1 = loop_face_tets1[i]
        face_vertices1 = loop_face_vertices1[i]

        face_opposite_vert0 = face_vertices0[3]
        face_tet0.unjoin(face_opposite_vert0)
        ### glue torus shell to the old tetrahedra

        vert_nums_Perm4 = regina.Perm4(vert_nums[0], vert_nums[1],
                                       vert_nums[2], 3)
        new_0_tets[i].join(3, face_tet0, face_vertices0 * vert_nums_Perm4)
        new_1_tets[i].join(3, face_tet1, face_vertices1 * vert_nums_Perm4)

    assert tri.isValid()
    assert tri.countBoundaryComponents(
    ) == original_countBoundaryComponents + 1

    if angle != None:
        for i in range(len(loop)):
            face_data = loop[i]
            face_index = face_data[0]
            face = original_tri.triangles()[face_index]
            vert_nums = face_data[1]

            face_embed0 = face.embedding(0)
            face_tet = face_embed0.simplex()
            face_vertices = face_embed0.vertices()
            face_opposite_vert = face_vertices[3]
            coor_points_out_of_tet0 = (tet_vert_coorientations[
                face_tet.index()][face_opposite_vert] == +1)

            # if (flow_agrees_with_regina_numbers != face_cor_agrees_with_regina_numbers) != coor_points_out_of_tet0:
            if coor_points_out_of_tet0:
                angle.extend([0, 2])
            else:
                angle.extend([2, 0])

        # print(sig, loop, angle, is_taut(tri, angle))
        assert is_taut(tri, angle)

    if branch != None:
        for i in range(len(loop)):
            branch.extend([1, 1])

        assert is_branched(tri, branch)

    M = snappy.Manifold(tri)
    if M.volume() < 1.0:
        print('not hyperbolic', sig, loop, angle, M.volume())
        assert False
        # print(M.verify_hyperbolicity())  ### very slow
        # print(M.volume())
        # assert M.volume() > 1.0 ###

    ### now orient
    swaps = [regina.Perm4()
             ] * original_countTetrahedra  ### identity permutations
    for i in range(len(loop)):
        if new_0_tets[i].adjacentGluing(3).sign() == 1:
            if angle != None:
                this_tet_angle = angle[original_countTetrahedra + 2 * i]
            else:
                this_tet_angle = 0  ### pi_location = 0 is an arbitrary choice
            swaps.append(
                reverse_tet_orientation(tri, new_0_tets[i], this_tet_angle))
        else:
            swaps.append(regina.Perm4())
        if new_1_tets[i].adjacentGluing(3).sign() == 1:
            if angle != None:
                this_tet_angle = angle[original_countTetrahedra + 2 * i + 1]
            else:
                this_tet_angle = 0  ### pi_location = 0 is an arbitrary choice
            swaps.append(
                reverse_tet_orientation(tri, new_1_tets[i], this_tet_angle))
        else:
            swaps.append(regina.Perm4())
    assert tri.isOriented()

    if angle != None:
        assert is_taut(tri, angle)
    if branch != None:
        # print('loop, branch, swaps', loop, branch, swaps)
        apply_swaps_to_branched_surface(branch, swaps)
        # print('loop, branch, swaps', loop, branch, swaps)
        assert is_branched(tri, branch)
        assert has_non_sing_semiflow(tri, branch)

    ### return the vertex of the triangulation corresponding to the drilled cusp
    drilled_cusp = new_0_tets[0].vertex(swaps[new_0_tets[0].index()][3])
    assert drilled_cusp.degree() == len(new_0_tets) + len(new_1_tets)
    return drilled_cusp.index()
Example #26
0
def edges_to_triangles_matrix(triangulation, angle_structure, cycles, ZH, P, mode = "taut"):
    # In mode alexander, we are computing the transpose of the
    # boundary operator from relative 1-chains to relative 0-chains of
    # the dual 2-complex (relative to its vertex set).  Note that we
    # technically should only be taking a single dual vertex
    # downstairs and lifting that... but then we would have to compute
    # a kernel.  By using all of the dual vertices we are splitting
    # off a free summand of the correct rank.

    # In mode "taut" we are computing the matrix which assigns to a
    # triangle the switch condition on its dual lower track
    coorientations = is_transverse_taut(triangulation, angle_structure, return_type = "tet_vert_coorientations")
    if verbose > 0:
        print(("coorientations", coorientations))
    face_laurents = faces_in_laurent(triangulation, angle_structure, cycles, ZH)
    if verbose > 0:
        print(("face_laurents", face_laurents))

    ET_matrix = [] # now to find the face coefficients relative to each edge
    for tet in triangulation.tetrahedra():
        # get its upper edge - we iterate over upper edges of tetrahedra
        if verbose > 0:
            print(("tet_index", tet.index()))
        edge = tet_lower_upper_edges(tet, coorientations)[1]
        if verbose > 0:
            print(("edge_index", edge.index()))
        embeddings = list(edge.embeddings())

        # find index of tet in the list of embeddings of edge
        for i, embed in enumerate(embeddings):
            tet = embed.tetrahedron()
            if verbose > 0:
                print(("current_tet", tet.index()))
            vert_perm = embed.vertices()
            trailing_vert_num, leading_vert_num = vert_perm[2], vert_perm[3]

            if (coorientations[tet.index()][trailing_vert_num] == +1 and
                coorientations[tet.index()][leading_vert_num]  == +1):
                bottom_index = i
                break

        # rotate
        embeddings = embeddings[bottom_index:] + embeddings[:bottom_index]

        face_coeffs = [ ZH(0) ] * 2 * triangulation.countTetrahedra()
        sign = -1 # we are going up the left side of the edge
        current_coeff = ZH(1)

        embed = embeddings[0]
        assert tet.index() == embed.tetrahedron().index() # sanity check

        if mode == "taut":
            # because of a sign change, we install the first and last by hand.
            vert_perm = embed.vertices()
            trailing_vert_num, leading_vert_num = vert_perm[2], vert_perm[3]
            leading_face = tet.triangle(trailing_vert_num)
            face_coeffs[leading_face.index()] = face_coeffs[leading_face.index()] + current_coeff
            trailing_face = tet.triangle(leading_vert_num)
            face_coeffs[trailing_face.index()] = face_coeffs[trailing_face.index()] + current_coeff
            if verbose > 0:
                print(("face_coeffs", face_coeffs))
            embeddings = embeddings[1:-1] # and remove them

        for embed in embeddings:
            tet = embed.tetrahedron()
            vert_perm = embed.vertices()
            trailing_vert_num, leading_vert_num = vert_perm[2], vert_perm[3]
            leading_face = tet.triangle(trailing_vert_num)
            trailing_face = tet.triangle(leading_vert_num)

            if sign == -1:
                use_face = trailing_face
            else: # sign == -1
                use_face = leading_face
            current_coeff = current_coeff * (face_laurents[use_face.index()])**sign
            if verbose > 0:
                print(("current_coeff", current_coeff))

            if (coorientations[tet.index()][trailing_vert_num] == -1 and 
                coorientations[tet.index()][leading_vert_num]  == -1): ## we are the top embed
                sign = 1 # so now are going down the right side of the edge
                current_coeff = current_coeff * (face_laurents[leading_face.index()])**sign
                if verbose > 0:
                    print(("top current_coeff", current_coeff))
            if mode == "taut":
                face_coeffs[leading_face.index()] = face_coeffs[leading_face.index()] - current_coeff
            elif mode == "alexander":
                face_coeffs[leading_face.index()] = face_coeffs[leading_face.index()] + sign*current_coeff
            if verbose > 0:
                print(("face_coeffs", face_coeffs))

        ET_matrix.append(face_coeffs)

    # convert and return
    return matrix_laurent_to_poly(ET_matrix, ZH, P)
Example #27
0
def run_tests(num_to_check=10, smaller_num_to_check = 10):

    import taut
    veering_isosigs = parse_data_file("Data/veering_census.txt")
    print("testing is_taut")
    for sig in random.sample(veering_isosigs, num_to_check):
        tri, angle = taut.isosig_to_tri_angle(sig)
        assert taut.is_taut(tri, angle), sig

    print("testing isosig round trip")
    for sig in random.sample(veering_isosigs, num_to_check):
        tri, angle = taut.isosig_to_tri_angle(sig)
        recovered_sig = taut.isosig_from_tri_angle(tri, angle)
        assert sig == recovered_sig, sig
        # we only test this round trip - the other round trip does not
        # make sense because tri->isosig is many to one.

    import transverse_taut
    print("testing is_transverse_taut")
    for sig in random.sample(veering_isosigs, num_to_check):
        tri, angle = taut.isosig_to_tri_angle(sig)
        assert transverse_taut.is_transverse_taut(tri, angle), sig

    non_transverse_taut_isosigs = parse_data_file("Data/veering_non_transverse_taut_examples.txt")
    print("testing not is_transverse_taut")
    for sig in non_transverse_taut_isosigs:
        tri, angle = taut.isosig_to_tri_angle(sig)
        assert not transverse_taut.is_transverse_taut(tri, angle), sig

    import veering
    print("testing is_veering")
    for sig in random.sample(veering_isosigs, num_to_check):
        tri, angle = taut.isosig_to_tri_angle(sig)
        assert veering.is_veering(tri, angle), sig

    # tri, angle = taut.isosig_to_tri_angle("cPcbbbdxm_10")
    # explore_mobius_surgery_graph(tri, angle, max_tetrahedra = 12)
    # # tests to see that it makes only veering triangulations as it goes

    import veering_dehn_surgery
    print("testing veering_dehn_surgery")
    for sig in random.sample(veering_isosigs, num_to_check):
        tri, angle = taut.isosig_to_tri_angle(sig)
        for face_num in veering_dehn_surgery.get_mobius_strip_indices(tri):
            (tri_s, angle_s, face_num_s) = veering_dehn_surgery.veering_mobius_dehn_surgery(tri, angle, face_num)
            assert veering.is_veering(tri_s, angle_s), sig
            
    import veering_fan_excision
    print("testing veering_fan_excision")
    m003, _ = taut.isosig_to_tri_angle('cPcbbbdxm_10')
    m004, _ = taut.isosig_to_tri_angle('cPcbbbiht_12')
    for sig in random.sample(veering_isosigs, num_to_check):
        tri, angle = taut.isosig_to_tri_angle(sig)
        tet_types = veering.is_veering(tri, angle, return_type = "tet_types")
        if tet_types.count("toggle") == 2:
            excised_tri, _ = veering_fan_excision.excise_fans(tri, angle)
            assert ( excised_tri.isIsomorphicTo(m003) != None or
                     excised_tri.isIsomorphicTo(m004) != None ), sig

    import pachner
    print("testing pachner with taut structure")
    for sig in random.sample(veering_isosigs, num_to_check):
        tri, angle = taut.isosig_to_tri_angle(sig)
        face_num = random.randrange(tri.countTriangles())
        result = pachner.twoThreeMove(tri, face_num, angle = angle, return_edge = True)  
        if result != False: 
            tri2, angle2, edge_num = result
            tri3, angle3 = pachner.threeTwoMove(tri2, edge_num, angle = angle2)
            assert taut.isosig_from_tri_angle(tri, angle) == taut.isosig_from_tri_angle(tri3, angle3), sig

    import branched_surface
    import regina
    print("testing branched_surface and pachner with branched surface")
    for sig in random.sample(veering_isosigs, num_to_check):
        tri, angle = taut.isosig_to_tri_angle(sig)
        tri_original = regina.Triangulation3(tri) #copy
        branch = branched_surface.upper_branched_surface(tri, angle, return_lower = random.choice([True, False]))
        
        ### test branch isosig round trip
        sig_with_branch = branched_surface.isosig_from_tri_angle_branch(tri, angle, branch)
        tri2, angle2, branch2 = branched_surface.isosig_to_tri_angle_branch(sig_with_branch)
        assert (branch == branch2) and (angle == angle2), sig

        branch_original = branch[:] #copy
        face_num = random.randrange(tri.countTriangles())
        out = pachner.twoThreeMove(tri, face_num, branch = branch, return_edge = True)
        if out != False:
            tri, possible_branches, edge_num = out
            tri, branch = pachner.threeTwoMove(tri, edge_num, branch = possible_branches[0])
            all_isoms = tri.findAllIsomorphisms(tri_original)
            all_branches = [branched_surface.apply_isom_to_branched_surface(branch, isom) for isom in all_isoms]
            assert branch_original in all_branches, sig

    import flow_cycles
    import drill
    print("testing taut and branched drill + semiflows on drillings")
    for sig in random.sample(veering_isosigs, smaller_num_to_check):
        tri, angle = taut.isosig_to_tri_angle(sig)
        branch = branched_surface.upper_branched_surface(tri, angle) ### also checks for veering and transverse taut
        found_loops = flow_cycles.find_flow_cycles(tri, branch)
        for loop in random.sample(found_loops, min(len(found_loops), 5)):  ## drill along at most 5 loops
            tri, angle = taut.isosig_to_tri_angle(sig)
            branch = branched_surface.upper_branched_surface(tri, angle) 
            tri_loop = flow_cycles.flow_cycle_to_triangle_loop(tri, branch, loop)
            if tri_loop != False: 
                if not flow_cycles.tri_loop_is_boundary_parallel(tri_loop, tri):
                    drill.drill(tri, tri_loop, angle = angle, branch = branch, sig = sig)
                    assert branched_surface.has_non_sing_semiflow(tri, branch), sig

    print("all basic tests passed")

    try:
        import snappy
        import snappy_util
        snappy_working = True
    except:
        print("failed to import from snappy?")
        snappy_working = False

    if snappy_working:        
        print("testing algebraic intersection")
        census = snappy.OrientableCuspedCensus() # not a set or list, so can't use random.sample
        for i in range(10):
            M = random.choice(census)
            n = M.num_cusps()
            peripheral_curves = M.gluing_equations()[-2*n:]
            for i in range(2*n):
                for j in range(i, 2*n):
                    alg_int = snappy_util.algebraic_intersection(peripheral_curves[i], peripheral_curves[j])
                    if i % 2 == 0 and j == i + 1:
                        assert alg_int == 1, M.name()
                    else:
                        assert alg_int == 0, M.name()
                       
    if snappy_working:
        import veering_drill_midsurface_bdy
        print("testing veering drilling and filling")
        for sig in random.sample(veering_isosigs[:3000], num_to_check):
            T, per = veering_drill_midsurface_bdy.drill_midsurface_bdy(sig)
            M = snappy.Manifold(T.snapPea())
            M.set_peripheral_curves("shortest")
            L = snappy_util.get_slopes_from_peripherals(M, per)
            M.dehn_fill(L)
            N = snappy.Manifold(sig.split("_")[0])
            assert M.is_isometric_to(N), sig

    if snappy_working:
        print("all tests depending on snappy passed")
   
    # try:
    #     from hashlib import md5
    #     from os import remove
    #     import pyx
    #     from boundary_triangulation import draw_triangulation_boundary_from_veering_isosig
    #     pyx_working = True
    # except:
    #     print("failed to import from pyx?")
    #     pyx_working = False

    # ladders_style_sigs = {
    #     "cPcbbbiht_12": "f34c1fdf65db9d02994752814803ae01",
    #     "gLLAQbecdfffhhnkqnc_120012": "091c85b4f4877276bfd8a955b769b496",
    #     "kLALPPzkcbbegfhgijjhhrwaaxnxxn_1221100101": "a0f15a8454f715f492c74ce1073a13a4",
    # }

    # geometric_style_sigs = {
    #     "cPcbbbiht_12": "1e74d0b68160c4922e85a5adb20a0f1d",
    #     "gLLAQbecdfffhhnkqnc_120012": "856a1fce74eb64f519bcda083303bd8f",
    #     "kLALPPzkcbbegfhgijjhhrwaaxnxxn_1221100101": "33bd23b34c5d977a103fa50ffe63120a",
    # }

    # args = {
    #     "draw_boundary_triangulation":True,
    #     "draw_triangles_near_poles": False,
    #     "ct_depth":-1,
    #     "ct_epsilon":0.03,
    #     "global_drawing_scale": 4,
    #     "delta": 0.2,
    #     "ladder_width": 10.0,
    #     "ladder_height": 20.0,
    #     "draw_labels": True,
    # }

    # shapes_data = read_from_pickle("Data/veering_shapes_up_to_ten_tetrahedra.pkl")

    # if pyx_working:
    #     for sig in ladders_style_sigs:
    #         print("testing boundary triangulation pictures, ladder style", sig)
    #         args["tet_shapes"] = shapes_data[sig]
    #         args["style"] = "ladders"
    #         file_name = draw_triangulation_boundary_from_veering_isosig(sig, args = args) 
    #         f = open(file_name, "rb")
    #         file_hash = md5(f.read())
    #         assert file_hash.hexdigest() == ladders_style_sigs[sig]
    #         f.close()
    #         remove(file_name)
        
    # if pyx_working:
    #     for sig in geometric_style_sigs:
    #         print("testing boundary triangulation pictures, ladder style", sig)
    #         args["tet_shapes"] = shapes_data[sig]
    #         args["style"] = "geometric"
    #         file_name = draw_triangulation_boundary_from_veering_isosig(sig, args = args) 
    #         f = open(file_name, "rb")
    #         file_hash = md5(f.read())
    #         assert file_hash.hexdigest() == geometric_style_sigs[sig]
    #         f.close()
    #         remove(file_name)

    # if pyx_working: 
    #     print("all tests depending on pyx passed")

    veering_polys = {
        "cPcbbbiht_12": [-4, -1, 1, 4],
        "eLMkbcddddedde_2100": [-2, -2, -2, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 2, 2],
        "gLLAQbecdfffhhnkqnc_120012": [-1, -1, -1, -1, 1, 1, 1, 1],
        "gLLPQcdfefefuoaaauo_022110": [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1],
    }

    # veering_polys = { ### old
    #     "cPcbbbiht_12": "a^3 - 4*a^2 + 4*a - 1",
    #     "eLMkbcddddedde_2100": "a^6*b - a^6 - 2*a^5*b - a^4*b^2 + a^5 + 2*a^4*b + a^3*b^2 - 2*a^3*b + a^3 + 2*a^2*b + a*b^2 - a^2 - 2*a*b - b^2 + b",
    #     "gLLAQbecdfffhhnkqnc_120012": "a^7 + a^6 + a^5 + a^4 - a^3 - a^2 - a - 1",
    #     "gLLPQcdfefefuoaaauo_022110": "a^12*b^3 - a^11*b^2 - a^10*b^3 - a^10*b^2 - a^7*b^3 - a^7*b^2 - a^6*b^3 + a^7*b + a^5*b^2 - a^6 - a^5*b - a^5 - a^2*b - a^2 - a*b + 1",
    # }

    taut_polys = {
        "cPcbbbiht_12": [-3, 1, 1],
        "eLMkbcddddedde_2100": [-1, -1, -1, 1, 1],
        "iLLAwQcccedfghhhlnhcqeesr_12001122": [],
    }

    # taut_polys = { ### old
    #     "cPcbbbiht_12": "a^2 - 3*a + 1",
    #     "eLMkbcddddedde_2100": "a^2*b - a^2 - a*b - b^2 + b",
    #     "iLLAwQcccedfghhhlnhcqeesr_12001122": "0",
    # }

    torus_bundles = [
        "cPcbbbiht_12",
        "eLMkbcdddhhqqa_1220",
        "gLMzQbcdefffhhqqqdl_122002",
    ]

    measured = [
        "gLLAQbecdfffhhnkqnc_120012",
        "iLLALQcccedhgghhlnxkxrkaa_12001112",
        "iLLAwQcccedfghhhlnhcqeesr_12001122",
    ]

    empties = [
        "fLAMcaccdeejsnaxk_20010",
        "gLALQbcbeeffhhwsras_211220",
        "hLALAkbcbeefgghhwsraqj_2112202",
    ]

    try:
        from sage.rings.integer_ring import ZZ
        sage_working = True
    except:
        print("failed to import from sage?")
        sage_working = False

    if sage_working:
        import taut_polytope
        print("testing is_layered")
        for sig in veering_isosigs[:17]:
            assert taut_polytope.is_layered(sig), sig
        for sig in veering_isosigs[17:21]:
            assert not taut_polytope.is_layered(sig), sig

    if sage_working:
        import fibered
        print("testing is_fibered")
        mflds = parse_data_file("Data/mflds_which_fiber.txt")
        mflds = [line.split("\t")[0:2] for line in mflds]
        for (name, kind) in random.sample(mflds, num_to_check):        
            assert fibered.is_fibered(name) == (kind == "fibered"), name

    if sage_working:
        import veering_polynomial
        import taut_polynomial
        print("testing veering poly")
        for sig in veering_polys:
            p = veering_polynomial.veering_polynomial(sig)
            assert check_polynomial_coefficients(p, veering_polys[sig]), sig
            ### Nov 2021: sage 9.4 changed how smith normal form works, which changed our polynomials
            ### to equivalent but not equal polynomials. To avoid this kind of change breaking things
            ### in the future, we changed to comparing the list of coefficients.
            # assert p.__repr__() == veering_polys[sig]
        print("testing taut poly")
        for sig in taut_polys:
            p = taut_polynomial.taut_polynomial_via_tree(sig)
            assert check_polynomial_coefficients(p, taut_polys[sig]), sig
        #     assert p.__repr__() == taut_polys[sig]
        print("testing divide")
        for sig in random.sample(veering_isosigs[:3000], num_to_check):
            p = veering_polynomial.veering_polynomial(sig)
            q = taut_polynomial.taut_polynomial_via_tree(sig)
            if q == 0:
                assert p == 0, sig
            else:
                assert q.divides(p), sig

    if sage_working:
        print("testing alex")
        for sig in random.sample(veering_isosigs[:3000], num_to_check):        
            snap_sig = sig.split("_")[0]
            M = snappy.Manifold(snap_sig)
            if M.homology().betti_number() == 1:
                assert taut_polynomial.taut_polynomial_via_tree(sig, mode = "alexander") == M.alexander_polynomial(), sig

    if sage_working:
        # would be nice to automate this - need to fetch the angle
        # structure say via z_charge.py...
        print("testing is_torus_bundle")
        for sig in torus_bundles: 
            assert taut_polytope.is_torus_bundle(sig), sig

    if sage_working:
        # ditto
        print("testing is_layered")
        for sig in torus_bundles:
            assert taut_polytope.is_layered(sig), sig
        print("testing measured")
        for sig in measured:
            assert taut_polytope.LMN_tri_angle(sig) == "M", sig
        print("testing empty")
        for sig in empties:
            assert taut_polytope.LMN_tri_angle(sig) == "N", sig

    if sage_working:  # warning - this takes random amounts of time!
        print("testing hom dim")
        for sig in random.sample(veering_isosigs[:3000], 3): # magic number
            # dimension = zero if and only if nothing is carried.
            assert (taut_polytope.taut_cone_homological_dim(sig) == 0) == (taut_polytope.LMN_tri_angle(sig) == "N"), sig

    if sage_working:      

        boundary_cycles = {
            ("eLMkbcddddedde_2100",(2,5,5,1,3,4,7,1)): "((-7, -7, 0, 0, 4, -3, 7, 0), (7, 7, 0, 0, -4, 3, -7, 0))",
            ("iLLLQPcbeegefhhhhhhahahha_01110221",(0,1,0,0,0,1,0,0,0,0,0,0,1,0,1,0)): "((0, 0, -1, 1, 1, 0, 1, 1, -1, 0, 0, 0, 0, 1, 0, 1), (0, 0, 1, -1, -1, 0, -1, -1, 1, 0, 0, 0, 0, -1, 0, -1))",
            ("ivvPQQcfhghgfghfaaaaaaaaa_01122000",(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)): "((1, 1, 2, 0, -1, 2, 1, -3, 0, -1, 0, -2, -1, 0, 3, -2), (1, 1, 0, 2, -1, 0, -3, 1, 2, -1, -2, 0, 3, -2, -1, 0), (-2, 0, -3, 1, 2, -1, 0, 2, -1, 0, 3, 1, -2, 1, 0, -1), (0, -2, 1, -3, 0, -1, 2, 0, -1, 2, -1, 1, 0, 1, -2, 3))",
        }

        taut_polys_with_cycles = {
            ("eLMkbcddddedde_2100", ((7, 7, 0, 0, -4, 3, -7, 0),)): [-1, -1, -1, 1, 1],
            ("iLLLQPcbeegefhhhhhhahahha_01110221", ((0, 0, 1, -1, -1, 0, -1, -1, 1, 0, 0, 0, 0, -1, 0, -1),)): [1, 1, 2],
            ("ivvPQQcfhghgfghfaaaaaaaaa_01122000", ((1, 1, 2, 0, -1, 2, 1, -3, 0, -1, 0, -2, -1, 0, 3, -2), (1, 1, 0, 2, -1, 0, -3, 1, 2, -1, -2, 0, 3, -2, -1, 0))): [-4, -1, -1, 1, 1],
        }

        # taut_polys_with_cycles = {
        #     ("eLMkbcddddedde_2100", ((7, 7, 0, 0, -4, 3, -7, 0),)): "a^14 - a^8 - a^7 - a^6 + 1",
        #     ("iLLLQPcbeegefhhhhhhahahha_01110221", ((0, 0, 1, -1, -1, 0, -1, -1, 1, 0, 0, 0, 0, -1, 0, -1),)): "a^2 + 2*a + 1",
        #     ("ivvPQQcfhghgfghfaaaaaaaaa_01122000", ((1, 1, 2, 0, -1, 2, 1, -3, 0, -1, 0, -2, -1, 0, 3, -2), (1, 1, 0, 2, -1, 0, -3, 1, 2, -1, -2, 0, 3, -2, -1, 0))): "a*b^2 - a^2 - 4*a*b - b^2 + a",
        # }


        taut_polys_image = {
            ('eLMkbcddddedde_2100', ((7, 8, -1, 0, -4, 4, -8, 0),)):[-1, -1, -1, 1, 1],
            ('ivvPQQcfhghgfghfaaaaaaaaa_01122000', ((1, 1, 2, 0, -1, 2, 1, -3, 0, -1, 0, -2, -1, 0, 3, -2),)):[-2, -2, -1, -1, 1, 1],
            ('ivvPQQcfhghgfghfaaaaaaaaa_01122000', ((1, 1, 2, 0, -1, 2, 1, -3, 0, -1, 0, -2, -1, 0, 3, -2), (1, 1, 0, 2, -1, 0, -3, 1, 2, -1, -2, 0, 3, -2, -1, 0))):[-4, -1, -1, 1, 1]
        }

        # taut_polys_image = {
        #     ('eLMkbcddddedde_2100', ((7, 8, -1, 0, -4, 4, -8, 0),)):"a^16 - a^9 - a^8 - a^7 + 1",
        #     ('ivvPQQcfhghgfghfaaaaaaaaa_01122000', ((1, 1, 2, 0, -1, 2, 1, -3, 0, -1, 0, -2, -1, 0, 3, -2),)):"a*b^2*c - 2*a*b*c - b^2*c - a^2 - 2*a*b + a",
        #     ('ivvPQQcfhghgfghfaaaaaaaaa_01122000', ((1, 1, 2, 0, -1, 2, 1, -3, 0, -1, 0, -2, -1, 0, 3, -2), (1, 1, 0, 2, -1, 0, -3, 1, 2, -1, -2, 0, 3, -2, -1, 0))):"a*b^2 - a^2 - 4*a*b - b^2 + a"
        # }

        alex_polys_with_cycles = {
            ("eLMkbcddddedde_2100",((7, 7, 0, 0, -4, 3, -7, 0),)): [-2, -1, -1, -1, 1, 1, 1, 2],
            ("iLLLQPcbeegefhhhhhhahahha_01110221", ((0, 0, 1, -1, -1, 0, -1, -1, 1, 0, 0, 0, 0, -1, 0, -1),)): [-3, -1, 1, 3],
            ("ivvPQQcfhghgfghfaaaaaaaaa_01122000", ((1, 1, 2, 0, -1, 2, 1, -3, 0, -1, 0, -2, -1, 0, 3, -2), (1, 1, 0, 2, -1, 0, -3, 1, 2, -1, -2, 0, 3, -2, -1, 0))): [-1, -1, 1, 1],
        }

        # alex_polys_with_cycles = {
        #     ("eLMkbcddddedde_2100",((7, 7, 0, 0, -4, 3, -7, 0),)): "a^15 - a^14 + a^9 - 2*a^8 + 2*a^7 - a^6 + a - 1",
        #     ("iLLLQPcbeegefhhhhhhahahha_01110221", ((0, 0, 1, -1, -1, 0, -1, -1, 1, 0, 0, 0, 0, -1, 0, -1),)): "3*a^3 - a^2 + a - 3",
        #     ("ivvPQQcfhghgfghfaaaaaaaaa_01122000", ((1, 1, 2, 0, -1, 2, 1, -3, 0, -1, 0, -2, -1, 0, 3, -2), (1, 1, 0, 2, -1, 0, -3, 1, 2, -1, -2, 0, 3, -2, -1, 0))): "a*b^2 - a^2 - b^2 + a",
        # }

    if sage_working:
        import taut_carried     
        print("testing boundary cycles")
        for sig, surface in boundary_cycles:
            surface_list = list(surface)
            cycles = taut_carried.boundary_cycles_from_surface(sig, surface_list)
            cycles = tuple(tuple(cycle) for cycle in cycles)
            assert cycles.__repr__() == boundary_cycles[(sig, surface)], sig

    if sage_working:
        print("testing taut with cycles")
        for sig, cycles in taut_polys_with_cycles:
            cycles_in = [list(cycle) for cycle in cycles]
            p = taut_polynomial.taut_polynomial_via_tree(sig, cycles_in)
            assert check_polynomial_coefficients(p, taut_polys_with_cycles[(sig, cycles)]), sig
            # assert p.__repr__() == taut_polys_with_cycles[(sig, cycles)]

    if sage_working:
        print("testing taut with images")
        for sig, cycles in taut_polys_image:
            cycles_in = [list(cycle) for cycle in cycles]
            p = taut_polynomial.taut_polynomial_image(sig, cycles_in)
            assert check_polynomial_coefficients(p, taut_polys_image[(sig, cycles)]), sig
            # assert p.__repr__() == taut_polys_image[(sig, cycles)]

    if sage_working:
        print("testing alex with cycles")
        for sig, cycles in alex_polys_with_cycles:
            cycles_in = [list(cycle) for cycle in cycles]
            p = taut_polynomial.taut_polynomial_via_tree(sig, cycles_in, mode = "alexander")
            assert check_polynomial_coefficients(p, alex_polys_with_cycles[(sig, cycles)]), sig
            # assert p.__repr__() == alex_polys_with_cycles[(sig, cycles)]

    if sage_working:
        import edge_orientability
        import taut_euler_class
        print("testing euler and edge orientability")
        for sig in random.sample(veering_isosigs[:3000], 3):
            # Theorem: If (tri, angle) is edge orientable then e = 0.
            assert not ( edge_orientability.is_edge_orientable(sig) and
                         (taut_euler_class.order_of_euler_class_wrapper(sig) == 2) ), sig

    if sage_working:
        # Theorem: If (tri, angle) is edge orientable then taut poly = alex poly.
        # taut_polynomial.taut_polynomial_via_tree(sig, mode = "alexander") ==
        #      taut_polynomial.taut_polynomial_via_tree(sig, mode = "taut")
        pass
            
    if sage_working:
        print("testing exotics")
        for sig in random.sample(veering_isosigs[:3000], 3):
            tri, angle = taut.isosig_to_tri_angle(sig)
            T = veering.veering_triangulation(tri, angle)
            is_eo = T.is_edge_orientable()
            for angle in T.exotic_angles():
                assert taut_polytope.taut_cone_homological_dim(tri, angle) == 0, sig
                assert is_eo == transverse_taut.is_transverse_taut(tri, angle), sig

    ### test for drill_midsurface_bdy: drill then fill, check you get the same manifold

    if sage_working:
        from sage.combinat.words.word_generators import words
        from sage.modules.free_module_integer import IntegerLattice
        from sage.modules.free_module import VectorSpace
        from sage.matrix.constructor import Matrix
        import z_charge
        import z2_taut
        import regina

        ZZ2 = ZZ.quotient(ZZ(2))

        sig_starts = ["b+-LR", "b++LR"]

        print("testing lattice for punc torus bundle")
        for i in range(3):
            for sig_start in sig_starts:
                sig = sig_start + str(words.RandomWord(8, 2, "LR"))  # 8 is a magic number
                M = snappy.Manifold(sig)
                tri = regina.Triangulation3(M)
                t, A = z_charge.sol_and_kernel(M)
                B = z_charge.leading_trailing_deformations(M)
                C = z2_taut.cohomology_loops(tri)

                AA = IntegerLattice(A)
                BB = IntegerLattice(B)
                assert AA == BB.saturation(), sig

                dim = 3*M.num_tetrahedra()
                V = VectorSpace(ZZ2, dim)
                AA = V.subspace(A)
                BB = V.subspace(B)
                CM = Matrix(ZZ2, C)
                CC = CM.right_kernel()
                assert AA.intersection(CC) == BB , sig
                ## so l-t defms are the part of the kernel that doesn't flip over

    if sage_working:
        print("testing charges for punc torus bundle")
        for i in range(3):
            for sig_start in sig_starts:
                sig = sig_start + str(words.RandomWord(8, 2, "LR"))  # 8 is a magic number
                M = snappy.Manifold(sig)
                assert z_charge.can_deal_with_reduced_angles(M), sig
    
    if sage_working:
        import carried_surface
        import mutation
        print("testing building carried surfaces and mutations")
        sigs_weights = [
            ['iLLLPQccdgefhhghqrqqssvof_02221000',  (0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0)], 
            ['jLLAvQQcedehihiihiinasmkutn_011220000', (2, 0, 1, 0, 0, 0, 1, 2, 0, 2, 0, 2, 1, 0, 0, 0, 1, 0)],
            ['jLLAvQQcedehihiihiinasmkutn_011220000', (0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0)],
            ['jLLLMPQcdgfhfhiiihshassspiq_122201101', (0, 0, 4, 0, 4, 1, 0, 2, 2, 0, 1, 0, 0, 4, 0, 4, 0, 0)]
        ]
        strata = [
            ((1, 2), [2, 2]), 
            ((2, 4), [5, 5, 1, 1]),
            ((0, 3), [2, 0, 0]),
            ((6, 1), [22])
        ]
        orders_of_veering_symmetry_groups = [4, 2, 2, 2]
        
        for i in range(len(sigs_weights)):
            tri, angle = taut.isosig_to_tri_angle(sigs_weights[i][0])
            weights = sigs_weights[i][1]
            surface, edge_colours = carried_surface.build_surface(tri, angle, weights, return_edge_colours = True)
            assert strata[i] == carried_surface.stratum_from_weights_surface(weights, surface)
            veering_isoms = carried_surface.veering_symmetry_group(surface, edge_colours)
            assert len(veering_isoms) == orders_of_veering_symmetry_groups[i]
            isom = veering_isoms[1]
            mutation.mutate(tri, angle, weights, isom, quiet = True)
            if i == 0:
                assert tri.isoSig() == 'ivLLQQccfhfeghghwadiwadrv'
                #print('svof to wadrv passed')
            elif i == 1:
                assert tri.isoSig() == 'jvLLAQQdfghhfgiiijttmtltrcr'
                #print('smkutn to tltrcr passed')
            elif i == 2:
                assert tri.isoSig() == 'jLLMvQQcedehhiiihiikiwnmtxk'
                #print('smkutn to mtxk passed')
            elif i == 3:
                assert tri.isoSig() == 'jLLALMQcecdhggiiihqrwqwrafo'
                #print('spiq to rafo passed')
                
                        
    if sage_working:
        print("all tests depending on sage passed")
Example #28
0
    # sig = 'eLMkbcddddedde_2100'
    # sig = 'eLMkbcdddhxqlm_1200'
    # sig = 'eLAkaccddjsnak_2001'
    # sig = 'eLAkbbcdddhwqj_2102'
    # sig = 'fLLQcbcdeeelonlel_02211'  ## should have three different midsurface bdy components, so four total after drilling
    # sig = 'fLLQcbddeeehrcdui_12000' ## five boundary components
    # sig = 'fLAMcbbcdeedhwqqs_21020'
    # sig = 'qvvLPQwAPLQkfhgffijlkmnopoppoaaaaaaaaaaaaadddd_1020212200111100'
    # t = excise_fans(sig)
    # t.save('excise_fans_' + sig + '.rga')

    # t0, _ = isosig_to_tri_angle('cPcbbbdxm_10')
    # t1, _ = isosig_to_tri_angle('cPcbbbiht_12')

    # print t.isIsomorphicTo(t0) != None or t.isIsomorphicTo(t1) != None

    # print fan_stacks(sig)

    import veering
    import transverse_taut
    import taut
    from file_io import parse_data_file
    census = parse_data_file('Data/veering_census.txt')

    for sig in census[:200]:
        tri, angle = excise_fans(sig)
        print((sig, tri.countTetrahedra(), angle, taut.is_taut(tri, angle)))
        assert veering.is_veering(tri, angle)
        assert transverse_taut.is_transverse_taut(tri, angle)
        # print sig, fan_stacks(sig)
Example #29
0
def is_edge_orientable(tri, angle, return_type="boolean"):
    """
    checks to see if this veering triangulation is edge orientable. 
    If return type is "tri angle" it returns the edge orientable double cover with its angle structure. 
    Note that this is disconnected if and only if the given triangulation is edge orientable
    """
    # return type can be "boolean", "veering_tet_vert_nums", or "tri angle"
    n = tri.countTetrahedra()
    veering_colours = is_veering(tri, angle, return_type="veering_colours")
    assert veering_colours != False  # so we are veering
    tet_vert_coorientations = is_transverse_taut(
        tri, angle, return_type="tet_vert_coorientations")

    ### assumption: the first n tetrahedra have upper edge oriented according to Regina, the last n have it against Regina

    ### build our own model vertex numbering for each tetrahedron as follows:
    ### the top edge e is oriented by regina numbering, and gets vert_nums 1 and 2 in our ordering
    ### an equatorial edge e' of the same colour as e shares a vertex v with it.
    ### e and e' both point away from v or towards it. If away then the other end of e' is 3,
    ### else, the other end is 0

    veering_tet_vert_nums = [
    ]  ### will populate with regina's vert nums, but our order.
    ### that is, veering_tet_vert_nums[1] and [2] will be the regina vert nums for the ends of the top edge

    for i in range(n):
        tet = tri.tetrahedron(i)
        veering_vert_nums = [None, None, None, None]
        top_vert_pair = get_tet_top_vert_nums(tet_vert_coorientations, i)
        # print(i, top_vert_pair)
        if not regina_edge_orientation_agrees(tet, top_vert_pair):
            top_vert_pair.reverse()
            assert regina_edge_orientation_agrees(tet, top_vert_pair)
        veering_vert_nums[1] = top_vert_pair[0]
        veering_vert_nums[2] = top_vert_pair[1]

        top_edge_num = vert_pair_to_edge_num[tuple(top_vert_pair)]
        top_edge_col = veering_colours[tet.edge(top_edge_num).index()]

        bottom_vert_pair = list(set(range(4)) - set(top_vert_pair))
        bv, bv2 = bottom_vert_pair  ## choose arbitrarily, now find which edge from the top vertices has same colour as bv
        for j, tv in enumerate(top_vert_pair):
            edge_col = veering_colours[tet.edge(
                vert_pair_to_edge_num[(bv, tv)]).index()]
            if edge_col == top_edge_col:
                if j == 0:  ### bv shares an edge of same colour as top with tail of top edge
                    veering_vert_nums[3] = bv
                    veering_vert_nums[0] = bv2
                else:  ### bv shares an edge of same colour as top with head of top edge
                    veering_vert_nums[0] = bv
                    veering_vert_nums[3] = bv2
        veering_tet_vert_nums.append(veering_vert_nums)
    # print('veering_tet_vert_nums', veering_tet_vert_nums)
    if return_type == "veering_tet_vert_nums":
        return veering_tet_vert_nums

    ### Now, when we glue two tetrahedra together along a face, the first of the three vertices in the veering_vert_num order
    ### on that tet's face glues to the first of the three vertices on the other tet's face, or to the third.
    ### depending on this, we go to the other part of the double cover, or not

    cover_tri = regina.Triangulation3()  ## starts empty
    for i in range(2 * n):
        cover_tri.newTetrahedron()
    tet_faces = []
    for i in range(n):
        for j in range(4):
            tet_faces.append((i, j))
    while len(tet_faces) > 0:
        i, j = tet_faces.pop()
        tet = tri.tetrahedron(i)
        adjtet, adjgluing = tet.adjacentTetrahedron(j), tet.adjacentGluing(j)
        iN, jN = adjtet.index(), adjgluing[j]
        tet_faces.remove((iN, jN))

        cover_tets = [cover_tri.tetrahedron(i), cover_tri.tetrahedron(i + n)]
        cover_tetsN = [
            cover_tri.tetrahedron(iN),
            cover_tri.tetrahedron(iN + n)
        ]
        ### find the veering indices for the verts in the gluing on this tet and on adjtet

        face_veering_nums = veering_tet_vert_nums[i][:]
        face_veering_nums.remove(j)
        a, b, c = face_veering_nums
        neighbour_face_veering_nums = veering_tet_vert_nums[iN][:]
        neighbour_face_veering_nums.remove(jN)
        aN, bN, cN = neighbour_face_veering_nums
        assert adjgluing[b] == bN  ### middles should match
        if adjgluing[a] == aN:  ### veering orderings agree across the gluing
            assert adjgluing[c] == cN
            for k in range(2):
                cover_tets[k].join(j, cover_tetsN[k], adjgluing)
        else:  ### veering orderings disagree across the gluing
            assert adjgluing[a] == cN and adjgluing[c] == aN
            for k in range(2):
                cover_tets[k].join(j, cover_tetsN[(k + 1) % 2], adjgluing)
    assert not cover_tri.hasBoundaryFacets()
    assert is_veering(cover_tri, angle + angle)

    if return_type == "boolean":
        return not cover_tri.isConnected(
        )  ### not connected if the original veering triangulation is edge orientable
    else:
        assert return_type == "tri angle"
        return cover_tri, angle + angle