Пример #1
0
def cross_strand(crossings, loose_cs, strand_to_cross, new_label):
    opposite = strand_to_cross.opposite()
    new_crossing = Crossing(new_label)
    crossings.append(new_crossing)
    cs0, cs1, cs2, cs3 = new_crossing.crossing_strands()
    connect_crossing_strands(cs0, loose_cs)
    connect_crossing_strands(cs1, strand_to_cross)
    connect_crossing_strands(cs3, opposite)
    return cs2
Пример #2
0
def random_knot(n,
                method='close_under',
                alternate=False,
                bias=False,
                num_opportunities=1):
    if method == 'close_under':
        crossings, loose_cs, final_cs = random_open_string(n,
                                                           alternate=alternate,
                                                           bias=bias)
        connect_loose_strands(crossings, loose_cs, final_cs)
        return Link(crossings)
    elif method == 'close_on_opportunity':
        crossings = [Crossing('0')]
        crossings[0][2] = crossings[0][3]
        final_cs = crossings[0].crossing_strands()[0]
        loose_cs = crossings[0].crossing_strands()[1]
        i = 0
        while num_opportunities > 0:
            available = available_strands(loose_cs)
            strand_to_cross = choice(available)
            if alternate:
                over_or_under = 1 - (i % 2)
            else:
                over_or_under = randint(0, 1)
            loose_cs = cross_strand(crossings, loose_cs, strand_to_cross,
                                    str(i + 1), over_or_under)
            same_face = set(available_strands(loose_cs)) == set(
                available_strands(final_cs))
            if same_face:
                num_opportunities -= 1
            i += 1
            if i >= n:
                raise Exception('Not closeable after n crossings')
        connect_loose_strands(crossings, loose_cs, final_cs)
        return Link(crossings)
Пример #3
0
def random_open_string(n):
    crossings = [Crossing('0')]
    crossings[0][2] = crossings[0][3]
    final_cs = crossings[0].crossing_strands()[0]
    loose_cs = crossings[0].crossing_strands()[1]
    for i in range(n):
        available = available_strands(loose_cs)
        #        print('available')
        #        print(available)
        #        print(loose_cs, final_cs)
        #        print('crossings before')
        #        [c.info() for c in crossings]
        if final_cs in available:
            available.remove(final_cs)
        strand_to_cross = choice(available)
        #       print('strand_to_cross')
        #        print(strand_to_cross)

        #        print('available after')
        #        print(available)
        loose_cs = cross_strand(crossings, loose_cs, strand_to_cross,
                                str(i + 1))


#        print('crossings after')
#        [c.info() for c in crossings]

    return crossings, loose_cs, final_cs
Пример #4
0
def cross_strand(crossings, loose_cs, strand_to_cross, new_label,
                 over_vs_under):
    opposite = strand_to_cross.opposite()
    new_crossing = Crossing(new_label)
    crossings.append(new_crossing)
    #    cs0, cs1, cs2, cs3 = new_crossing.crossing_strands()
    #    connect_crossing_strands(cs0, loose_cs)
    #    connect_crossing_strands(cs1, strand_to_cross)
    #    connect_crossing_strands(cs3, opposite)

    css = new_crossing.crossing_strands()
    connect_crossing_strands(css[0 + over_vs_under], loose_cs)
    connect_crossing_strands(css[1 + over_vs_under], strand_to_cross)
    connect_crossing_strands(css[(3 + over_vs_under) % 4], opposite)

    return css[2 + over_vs_under]
Пример #5
0
def open_string_from_turn_list(turn_list):
    crossings = [Crossing('0')]
    crossings[0][2] = crossings[0][3]
    final_cs = crossings[0].crossing_strands()[0]
    loose_cs = crossings[0].crossing_strands()[1]
    for i, turn in enumerate(turn_list):
        available = available_strands(loose_cs)
        #        print('available')
        #        print(available)
        #        print(loose_cs, final_cs)
        #        print('crossings before')
        #        [c.info() for c in crossings]
        if final_cs in available:
            available.remove(final_cs)
        strand_to_cross = available[(abs(turn) - 1) % len(available)]
        #       print('strand_to_cross')
        #        print(strand_to_cross)

        #        print('available after')
        #        print(available)
        loose_cs = cross_strand(crossings, loose_cs, strand_to_cross,
                                str(i + 1), (turn > 0))


#        print('crossings after')
#        [c.info() for c in crossings]

    return crossings, loose_cs, final_cs
Пример #6
0
 def link(self):
     active = dict()
     component_starts = []
     crossings = []
     for event in self.events:
         if event.kind == 'cup':
             S = Strand()
             crossings.append(S)
             active = insert_space(active, event.min)
             active[event.a] = S[0]
             active[event.b] = S[1]
         elif event.kind == 'cap':
             S = Strand()
             crossings.append(S)
             S[0] = active[event.a]
             S[1] = active[event.b]
             active = remove_space(active, event.min)
         elif event.kind == 'cross':
             C = Crossing()
             crossings.append(C)
             if event.a < event.b:
                 C[3] = active[event.a]
                 C[0] = active[event.b]
                 active[event.a] = C[2]
                 active[event.b] = C[1]
             else:
                 C[3] = active[event.a]
                 C[2] = active[event.b]
                 active[event.a] = C[0]
                 active[event.b] = C[1]
     return Link(crossings)
Пример #7
0
def mirror(link):
    """
    Create the mirror image of the link, preserving link orientations and
    component order.
    """
    # Basically, we just mirror every crossing, but the particular data 
    # structures used make this a little involved.
    
    new_crossings = dict()
    for C in link.crossings:
        C_new = Crossing(label=C.label)
        C_new.sign = -C.sign
        new_crossings[C] = C_new

    def convert(C, c):
        """
        Go from a crossing to the mirror, which requires the a rotation of the
        entry points; the direction of rotation depends on the sign of
        the crossing.
        """
        return new_crossings[C], (c + C.sign) % 4
        
    for A in link.crossings:
        entry_points = [CEP.entry_point for CEP in A.entry_points()]
        for a in entry_points:
            B, b = A.adjacent[a]
            B_new, b_new = convert(B, b)
            B_new[b_new] = convert(A, a)

    new_link = Link(new_crossings.values(),
                    check_planarity=False, build=False)

    # Build the link components, starting in the same place as
    # the original link.
    
    component_starts = []
    for component in link.link_components:
        C_new, c_new = convert(*component[0])
        component_starts.append( CrossingEntryPoint(C_new, c_new) )

    new_link._build_components(component_starts)
    return new_link
Пример #8
0
 def link(self):
     G = self.fat_graph
     crossing_dict, slot_dict = {}, {}
     for v in G.vertices:
         c = Crossing(v[0])
         c.make_tail(0)
         if G.sign(v) == 1:
             c.make_tail(3)
         else:
             c.make_tail(1)
         c.orient()
         crossing_dict[v] = c
         if v.upper_pair() == (0, 2):
             slot_dict[v] = (3, 0, 1, 2)
         else:
             slot_dict[v] = (2, 3, 0, 1) if G.flipped(v) else (0, 1, 2, 3)
     for edge in G.edges:
         v0, v1 = edge
         s0, s1 = edge.slots
         a0, a1 = slot_dict[v0][s0], slot_dict[v1][s1]
         c0, c1 = crossing_dict[v0], crossing_dict[v1]
         c0[a0] = c1[a1]
     link = Link(list(crossing_dict.values()),
                 check_planarity=False,
                 build=False)
     assert link.all_crossings_oriented()
     component_starts = []
     i = 1
     for comp in self.code:
         c = self[i]
         if i == c[0]:
             e = slot_dict[c][2] if G.flipped(c) else slot_dict[c][0]
         else:
             e = slot_dict[c][1]
         ce = CrossingEntryPoint(crossing_dict[c], e)
         component_starts.append(ce)
         i += 2 * len(comp)
     link._build_components(component_starts)
     if not link.is_planar():
         raise ValueError(
             'DT code does not seem to define a *planar* diagram')
     return link
Пример #9
0
def knot_tree(depth):
    crossings = [Crossing('0')]
    crossings[0][2] = crossings[0][3]
    final_cs = crossings[0].crossing_strands()[0]
    loose_cs = crossings[0].crossing_strands()[1]
    tree = nx.Graph()
    tree.add_node('')
    leaves = ['']
    for i in range(depth):
        print(i)
        leaves = split_leaves(tree, leaves)
    return tree, [map(int, leaf.split()) for leaf in leaves]
Пример #10
0
def gausscode_to_crossings(gc):
    cl = gc._gauss_code
    crossings = []
    incomplete_crossings = {}
    line_lengths = [len(line) for line in cl]
    total_lines = sum(line_lengths)
    line_indices = [1] + list(n.cumsum(line_lengths)[:-1] + 1)

    curline = 1
    for i, line in enumerate(cl):
        curline = line_indices[i]
        for index, over, clockwise in line:
            if index in incomplete_crossings:
                crossing = incomplete_crossings.pop(index)
            else:
                crossing = Crossing()

            inline = curline
            curline += 1
            if curline >= (line_indices[i] + line_lengths[i]):
                curline = line_indices[i]
            outline = curline

            if over == -1:
                crossing[0] = inline
                crossing[2] = outline
                crossings.append(crossing)
            else:
                if clockwise == 1:
                    crossing[3] = inline
                    crossing[1] = outline
                else:
                    crossing[1] = inline
                    crossing[3] = outline

            if not crossing.valid():
                incomplete_crossings[index] = crossing

    return crossings
Пример #11
0
 def link(self):
     G = self.fat_graph
     crossing_dict = {}
     for v in G.vertices:
         c = Crossing(v[0])
         c.make_tail(0)
         if G.sign(v) == 1:
             c.make_tail(3)
         else:
             c.make_tail(1)
         c.orient()
         crossing_dict[v] = c
     for edge in G.edges:
         if edge.slots[0] in edge[0].upper_pair():
             a = 1 if G.sign(edge[0]) == 1 else 3
         else:
             a = 2
         if edge.slots[1] in edge[1].upper_pair():
             b = 3 if G.sign(edge[1]) == 1 else 1
         else:
             b = 0
         crossing_dict[edge[0]][a] = crossing_dict[edge[1]][b]
     return Link(crossing_dict.values(), check_planarity=False)
Пример #12
0
def shorthand_to_crossings(s):
    '''
    Takes a planar diagram shorthand string, and returns a list of
    :class:`Crossing`s.
    '''
    crossings = []
    cs = s.split(' ')
    for entry in cs:
        entry = entry.split('_')
        if entry[0] == 'X':
            a, b, c, d = [int(j) for j in entry[1].split(',')]
            crossings.append(Crossing(a, b, c, d))
        elif entry[0] == 'P':
            a, b = [int(j) for j in entry[1].split(',')]
            crossings.append(Point(a, b))
    return crossings
Пример #13
0
def alexander_evolution(n):
    crossings = [Crossing('0')]
    crossings[0][2] = crossings[0][3]
    final_cs = crossings[0].crossing_strands()[0]
    loose_cs = crossings[0].crossing_strands()[1]
    alex_polys = []
    for i in range(n):
        print(i)
        available = available_strands(loose_cs)
        if final_cs in available:
            available.remove(final_cs)
        strand_to_cross = choice(available)
        loose_cs = cross_strand(crossings, loose_cs, strand_to_cross,
                                str(i + 1), randint(0, 1))
        alex_polys.append(open_string_alexander(crossings))
    return alex_polys
Пример #14
0
def random_open_string(n, alternate=False, bias=False):
    crossings = [Crossing('0')]
    crossings[0][2] = crossings[0][3]
    final_cs = crossings[0].crossing_strands()[0]
    loose_cs = crossings[0].crossing_strands()[1]
    for i in range(n):
        available = available_strands(loose_cs)
        if bias:
            strand_to_cross = choice(bias_middle(available))
        else:
            strand_to_cross = choice(available)
        if alternate:
            over_or_under = 1 - (i % 2)
        else:
            over_or_under = randint(0, 1)
        loose_cs = cross_strand(crossings, loose_cs, strand_to_cross,
                                str(i + 1), over_or_under)
    return crossings, loose_cs, final_cs
Пример #15
0
def function_evolution(n, function, simplify='level', skip_first=0):
    crossings = [Crossing('0')]
    crossings[0][2] = crossings[0][3]
    final_cs = crossings[0].crossing_strands()[0]
    loose_cs = crossings[0].crossing_strands()[1]
    values = []
    for i in range(n):
        print(i)
        available = available_strands(loose_cs)
        if final_cs in available:
            available.remove(final_cs)
        strand_to_cross = choice(available)
        loose_cs = cross_strand(crossings, loose_cs, strand_to_cross,
                                str(i + 1), randint(0, 1))
        if i >= skip_first:
            values.append(open_string_evaluation(crossings, function,
                                                 simplify))
    return values
Пример #16
0
    def as_spherogram(self):
        '''
        Get a planar diagram class from the Spherogram module, which
        can be used to access SnapPy's manifold tools.

        This method requires that spherogram and SnapPy are installed.
        '''
        from spherogram import Crossing, Link
        scs = [Crossing() for crossing in self]

        indices = {}
        for i in range(len(self)):
            c = self[i]
            for j in range(len(c)):
                number = c[j]
                if number in indices:
                    otheri, otherj = indices.pop(number)
                    scs[i][j] = scs[otheri][otherj]
                else:
                    indices[number] = (i, j)
        return Link(scs)
Пример #17
0
def start_string():
    crossings = [Crossing('0')]
    crossings[0][2] = crossings[0][3]
    final_cs = crossings[0].crossing_strands()[0]
    loose_cs = crossings[0].crossing_strands()[1]
    return crossings, loose_cs, final_cs