Esempio n. 1
0
def tangle_cut(link, cycle):
    """
    Creates two Tangle objects from a given cycle (with no self intersections)
    in the dual graph of a link (inside and outside).  Cycle is given
    as a list of (oriented) edges in the dual graph. Make sure crossings 
    are uniquely labeled. Destroys original link.
    """

    sides = {
    }  #keeps track of which side each crossing strand is as dictionary
    sides[cslabel(
        cycle[0].interface[0])] = 0  #start by assigning to first pair
    sides[cslabel(cycle[0].interface[1])] = 1  #sides
    side0 = [cycle[0].interface[0]]
    side1 = [cycle[0].interface[1]]
    for i in range(len(cycle) - 1):
        #        print(i)
        edge1 = cycle[i]
        edge2 = cycle[i + 1]
        edge1_cs1, edge1_cs2 = edge1.interface  #crossing strands on each end
        edge2_cs1, edge2_cs2 = edge2.interface
        edge1_cs1_side = sides[cslabel(edge1_cs1)]
        edge1_cs2_side = 1 - edge1_cs1_side

        wrong_face = False
        #starting with edge1_cs1, travel around face
        #if I run into one of edge2_cs*, they are on different sides
        #if I don't, try again with the other
        while True:
            #            print('sides:')
            #            print(sides)
            #            print('edge1:')
            #            print(edge1_cs1,edge1_cs2)
            #            print('edge2:')
            #            print(edge2_cs1,edge2_cs2)
            edge1_cs1 = edge1_cs1.next_corner()
            #            print(type(edge1_cs1.crossing.label))
            #            print(edge1_cs1)
            if edge1_cs1 == edge2_cs1:
                sides[cslabel(edge2_cs1)] = edge1_cs2_side
                sides[cslabel(edge2_cs2)] = edge1_cs1_side
                if edge1_cs2_side == 1:
                    side1.append(edge2_cs1)
                    side0.append(edge2_cs2)
                else:
                    side0.append(edge2_cs1)
                    side1.append(edge2_cs2)
#                print('case 1')
                break
            if edge1_cs1 == edge2_cs2:
                sides[cslabel(edge2_cs1)] = edge1_cs1_side
                sides[cslabel(edge2_cs2)] = edge1_cs2_side
                if edge1_cs2_side == 1:
                    side0.append(edge2_cs1)
                    side1.append(edge2_cs2)
                else:
                    side1.append(edge2_cs1)
                    side0.append(edge2_cs2)


#                print('case 2')
                break
            if edge1_cs1.opposite(
            ) == edge1_cs2:  #returned without seeing them
                wrong_face = True
                #                print('case 3')
                break

        # Try again with other side
        while wrong_face:
            edge1_cs1_side = sides[cslabel(edge1_cs1)]
            edge1_cs2_side = 1 - edge1_cs1_side
            edge1_cs2 = edge1_cs2.next_corner()
            if edge1_cs2 == edge2_cs1:
                #                print('case 4')
                sides[cslabel(edge2_cs1)] = edge1_cs1_side
                sides[cslabel(edge2_cs2)] = edge1_cs2_side
                if edge1_cs2_side == 1:
                    side0.append(edge2_cs1)
                    side1.append(edge2_cs2)
                else:
                    side1.append(edge2_cs1)
                    side0.append(edge2_cs2)
                break
            if edge1_cs2 == edge2_cs2:
                #               print('case 5')
                sides[cslabel(edge2_cs1)] = edge1_cs2_side
                sides[cslabel(edge2_cs2)] = edge1_cs1_side
                if edge1_cs2_side == 1:
                    side1.append(edge2_cs1)
                    side0.append(edge2_cs2)
                else:
                    side0.append(edge2_cs1)
                    side1.append(edge2_cs2)
                break
            if edge1_cs2.opposite(
            ) == edge1_cs1:  #returned without seeing them again, must be error
                raise Exception("Neither side worked")

    crossing_sides = fill_in_crossings(link, sides)
    n = len(cycle)
    side0[n / 2:] = reversed(side0[n / 2:])  #flip to use as adjacent in tangle
    side1[n / 2:] = reversed(side1[n / 2:])
    crossings0 = [
        crossing_from_name(link, c) for c in crossing_sides
        if crossing_sides[c] == 0
    ]
    crossings1 = [
        crossing_from_name(link, c) for c in crossing_sides
        if crossing_sides[c] == 1
    ]

    #clear crossing info
    clear_orientations(crossings0)
    clear_orientations(crossings1)

    #One of the tangles is the 'outside', and needs to be flipped
    #Just check side0
    side0_needs_flip = False
    c, i = side0[0]
    while True:
        next_cep = c.crossing_strands()[(i + 1) % 4]
        c, i = next_cep.crossing, next_cep.strand_index
        #        print(c,i)
        #        print(side0)
        if (c, i) in side0:
            #            print('hit_end')
            #            print(c,i)
            #            print(side0[1])
            #            print((c,i)==side0[1])
            side0_needs_flip = (c, i) != (side0[1])
            break
        c, i = next_cep.opposite().crossing, next_cep.opposite().strand_index
    if side0_needs_flip:
        #        print('flipped side 0')
        flip(side0)
    else:
        #        print('flipped side 1')
        flip(side1)
    return Tangle(n / 2, crossings0, side0), Tangle(n / 2, crossings1, side1)
Esempio n. 2
0
def tangle_neighborhood(link,
                        crossing,
                        radius,
                        return_gluings=True,
                        hull=False):
    """
    Splits a link into two tangles along a ball around a crossing of the given
    radius.  Destroys original link.  This might not generate an actual tangle;
    the graph metric ball will usually have multiple boundary components.
    """

    crossings, adjacent = crossing_ball(crossing, radius)
    crossings = list(crossings)

    opposites = list(reversed(map(lambda x: x.opposite(), adjacent)))
    outside_crossings = [c for c in link.crossings if c not in crossings]
    if len(outside_crossings) == 0:
        raise Exception("Neighborhood is entire link")
    n = len(adjacent) / 2

    if hull:
        comps = list(boundary_components(link, crossing, radius))
        largest_comp = max(comps)
        sides = dict([(cslabel(cross_strand), cross_strand)
                      for cross_strand in adjacent])
        c = largest_comp.pop()
        cs = choice(c.crossing_strands())
        exit_strand = meander(cs, sides)[1]
        exit_strand = exit_strand[0].crossing_strands()[exit_strand[1]]
        main_boundary_comp = trace_boundary_component(exit_strand, adjacent)
        print('main_boundary_comp' + str(main_boundary_comp))
        print('all comps: ' + str(comps))
        comps.remove(largest_comp)  #remove largest component
        for comp in comps:
            print('crossings: ' + str(crossings))
            print('filling in comp:' + str(comp))
            print('adjacent: ' + str(adjacent))
            c = comp.pop()
            cs = choice(c.crossing_strands())

            print('cs: ' + str(cs))
            exit_strand = meander(cs,
                                  sides)[1]  #meander until you hit boundary
            exit_strand = exit_strand[0].crossing_strands()[exit_strand[1]]
            print('exit_strand: ' + str(exit_strand))
            bound_comp = trace_boundary_component(exit_strand, adjacent)
            print('traced component: ' + str(bound_comp))
            if exit_strand not in main_boundary_comp:
                for x in bound_comp:
                    adjacent.remove(x)
                print('updated adjacent: ' + str(adjacent))
                crossings.append(c)
                crossings.extend(list(comp))

    adjacent[n:] = reversed(adjacent[n:])
    opposites[n:] = reversed(opposites[n:])
    gluings = []
    seen_cs = []
    # figure out which strands are glued to each other
    for cs in adjacent:
        if cs in seen_cs:
            continue
        next_cross = cs.next_corner()
        while next_cross not in adjacent:
            next_cross = next_cross.next_corner()
        if next_cross != cs:
            gluings.append((adjacent.index(cs), adjacent.index(next_cross)))
            seen_cs.append(next_cross)
    clear_orientations(crossings)
    clear_orientations(outside_crossings)
    gluings.sort()
    if return_gluings:
        return Tangle(n, crossings, adjacent), Tangle(n, outside_crossings,
                                                      opposites), gluings
    else:
        return Tangle(n, crossings, adjacent), Tangle(n, outside_crossings,
                                                      opposites)