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)
def open_string_alexander(crossings): crossings_copy = pickle.loads(pickle.dumps(crossings)) loose = [] for c in crossings_copy: for i in range(4): if c.adjacent[i] is None: loose.append(c.crossing_strands()[i]) connect_loose_strands(crossings_copy, loose[0], loose[1]) K = Link(crossings_copy) K.simplify(mode='level') return K.alexander_polynomial() if len(K) > 0 else 1
def open_string_evaluation(crossings, function, simplify='level'): crossings_copy = pickle.loads(pickle.dumps(crossings)) loose = [] for c in crossings_copy: for i in range(4): if c.adjacent[i] is None: loose.append(c.crossing_strands()[i]) connect_loose_strands(crossings_copy, loose[0], loose[1]) K = Link(crossings_copy) if simplify: K.simplify(mode=simplify) if len(K) > 0: return function(K)
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)
def link(self): crossings = [] curr_endpoints = self.width * [None] for x, y in self.bottom: s = Strand() crossings.append(s) curr_endpoints[x] = (s, 0) curr_endpoints[y] = (s, 1) for a, b in self.crossings: c = Crossing() crossings.append(c) if a < b: ins, outs = (3, 0), (2, 1) else: ins, outs = (0, 1), (3, 2) a, b = b, a c[ins[0]] = curr_endpoints[a] c[ins[1]] = curr_endpoints[b] curr_endpoints[a] = (c, outs[0]) curr_endpoints[b] = (c, outs[1]) for x, y in self.top: join_strands(curr_endpoints[x], curr_endpoints[y]) return Link(crossings)
def open_string_volume(crossings): crossings_copy = pickle.loads(pickle.dumps(crossings)) loose = [] for c in crossings_copy: for i in range(4): if c.adjacent[i] is None: loose.append(c.crossing_strands()[i]) connect_loose_strands(crossings_copy, loose[0], loose[1]) return Link(crossings_copy).exterior().volume()
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
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)
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)
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
def test_jones(): from spherogram import Link L = Link('L11a548') E = good_exhaustion(L, max_failed_tries=100) print(E.jones_polynomial())
def test_kauffman(): from spherogram import Link L = Link('L11a548') E = good_exhaustion(L) return E.kauffman_bracket()
def random_knot(n): crossings, loose_cs, final_cs = random_open_string(n) flip_crossings(crossings, loose_cs, final_cs) # print(open_string_faces(crossings, loose_cs, final_cs)) connect_loose_strands(crossings, loose_cs, final_cs) return Link(crossings)
def basic_test(): for M in snappy.LinkExteriors(): if M.solution_type().startswith('all tetra'): L = Link(M.name()) test_link(L)
from spherogram import Link, Crossing from spherogram.links.links import CrossingEntryPoint import snappy L = Link('9^3_12') #L = Link('4a1') 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()]
def knot_from_turn_list(turn_list): crossings, loose_cs, final_cs = open_string_from_turn_list(turn_list) # randomly_flip_crossings(crossings, loose_cs, final_cs) # print(open_string_faces(crossings, loose_cs, final_cs)) connect_loose_strands(crossings, loose_cs, final_cs) return Link(crossings)