def braid_word(self, as_sage_braid=False): """ Return a list of integers which defines a braid word whose closure is the given link. The natural numbers 1, 2, 3, etc are the generators and the negatives are the inverses. >>> L = Link('K8n1') >>> word = L.braid_word(); word [1, -2, 3, 2, 4, -3, 2, -1, 2, 2, 3, 2, -4, -3, -2, -2] >>> Link(braid_closure=word).exterior().identify() # doctest: +SNAPPY [m222(0,0), 8_20(0,0), K5_12(0,0), K8n1(0,0)] Within Sage, you can get the answer as an element of the appropriate BraidGroup:: sage: Link('K6a2').braid_word(as_sage_braid=True) (s0^-1*s1)^2*s0^-2 Implementation follows P. Vogel, "Representation of links by braids, a new algorithm". """ from . import seifert word = seifert.braid_word(self) if as_sage_braid: if not _within_sage: raise ValueError('Requested Sage braid outside of Sage.') n = max([abs(a) for a in word]) + 1 word = BraidGroup(n)(word) return word
def braid_word(self, as_sage_braid=False): """ Return a list of integers which defines a braid word whose closure is the given link. The natural numbers 1, 2, 3, etc are the generators and the negatives are the inverses. >>> L = Link('K6a2') >>> word = L.braid_word() >>> B = Link(braid_closure=word) >>> B.exterior().identify() # doctest: +SNAPPY [m289(0,0), 6_2(0,0), K5_19(0,0), K6a2(0,0)] Within Sage, you can get the answer as an element of the appropriate BraidGroup and also check our earlier work:: sage: Link('K6a2').braid_word(as_sage_braid=True) (s0*s1^-1)^2*s0^2 sage: L.signature(), B.signature() (-2, -2) Implementation follows P. Vogel, "Representation of links by braids, a new algorithm". """ from . import seifert word = seifert.braid_word(self) if as_sage_braid: if not _within_sage: raise ValueError('Requested Sage braid outside of Sage.') n = max(abs(a) for a in word) + 1 word = BraidGroup(n)(word) return word
def __classcall_private__(cls, coxeter_data, names=None): """ Normalize input to ensure a unique representation. TESTS:: sage: A1 = ArtinGroup(['B',3]) sage: A2 = ArtinGroup(['B',3], 's') sage: A3 = ArtinGroup(['B',3], ['s1','s2','s3']) sage: A1 is A2 and A2 is A3 True sage: A1 = ArtinGroup(['B',2], 'a,b') sage: A2 = ArtinGroup([[1,4],[4,1]], 'a,b') sage: A3.<a,b> = ArtinGroup('B2') sage: A1 is A2 and A2 is A3 True sage: ArtinGroup(['A',3]) is BraidGroup(4, 's1,s2,s3') True sage: G = graphs.PathGraph(3) sage: CM = CoxeterMatrix([[1,-1,2],[-1,1,-1],[2,-1,1]], index_set=G.vertices()) sage: A = groups.misc.Artin(CM) sage: Ap = groups.misc.RightAngledArtin(G, 's') sage: A is Ap True """ coxeter_data = CoxeterMatrix(coxeter_data) if names is None: names = 's' if isinstance(names, six.string_types): if ',' in names: names = [x.strip() for x in names.split(',')] else: names = [names + str(i) for i in coxeter_data.index_set()] names = tuple(names) if len(names) != coxeter_data.rank(): raise ValueError("the number of generators must match" " the rank of the Coxeter type") if all(m == Infinity for m in coxeter_data.coxeter_graph().edge_labels()): from sage.groups.raag import RightAngledArtinGroup return RightAngledArtinGroup(coxeter_data.coxeter_graph(), names) if not coxeter_data.is_finite(): raise NotImplementedError if coxeter_data.coxeter_type().cartan_type().type() == 'A': from sage.groups.braid import BraidGroup return BraidGroup(coxeter_data.rank() + 1, names) return FiniteTypeArtinGroup(coxeter_data, names)
def braid_from_piecewise(strands): r""" Compute the braid corresponding to the piecewise linear curves strands. INPUT: - ``strands`` -- a list of lists of tuples ``(t, c)``, where ``t`` is a number bewteen 0 and 1, and ``c`` is a complex number OUTPUT: The braid formed by the piecewise linear strands. EXAMPLES:: sage: from sage.schemes.curves.zariski_vankampen import braid_from_piecewise # optional - sirocco sage: paths = [[(0, I), (0.2, -1 - 0.5*I), (0.8, -1), (1, -I)], ....: [(0, -1), (0.5, -I), (1, 1)], ....: [(0, 1), (0.5, 1 + I), (1, I)]] sage: braid_from_piecewise(paths) # optional - sirocco s0*s1 """ L = strands i = min(val[1][0] for val in L) totalpoints = [[[a[0][1].real(), a[0][1].imag()]] for a in L] indices = [1 for a in range(len(L))] while i < 1: for j, val in enumerate(L): if val[indices[j]][0] > i: xaux = val[indices[j] - 1][1] yaux = val[indices[j]][1] aaux = val[indices[j] - 1][0] baux = val[indices[j]][0] interpola = xaux + (yaux - xaux)*(i - aaux)/(baux - aaux) totalpoints[j].append([interpola.real(), interpola.imag()]) else: totalpoints[j].append([val[indices[j]][1].real(), val[indices[j]][1].imag()]) indices[j] = indices[j] + 1 i = min(val[indices[k]][0] for k,val in enumerate(L)) for j, val in enumerate(L): totalpoints[j].append([val[-1][1].real(), val[-1][1].imag()]) braid = [] G = SymmetricGroup(len(totalpoints)) def sgn(x, y): # Opposite sign of cmp if x < y: return 1 if x > y: return -1 return 0 for i in range(len(totalpoints[0]) - 1): l1 = [totalpoints[j][i] for j in range(len(L))] l2 = [totalpoints[j][i+1] for j in range(len(L))] M = [[l1[s], l2[s]] for s in range(len(l1))] M.sort() l1 = [a[0] for a in M] l2 = [a[1] for a in M] cruces = [] for j in range(len(l2)): for k in range(j): if l2[j] < l2[k]: t = (l1[j][0] - l1[k][0])/(l2[k][0] - l1[k][0] + l1[j][0] - l2[j][0]) s = sgn(l1[k][1]*(1 - t) + t*l2[k][1], l1[j][1]*(1 - t) + t*l2[j][1]) cruces.append([t, k, j, s]) if cruces: cruces.sort() P = G(Permutation([])) while cruces: # we select the crosses in the same t crucesl = [c for c in cruces if c[0]==cruces[0][0]] crossesl = [(P(c[2]+1) - P(c[1]+1),c[1],c[2],c[3]) for c in crucesl] cruces = cruces[len(crucesl):] while crossesl: crossesl.sort() c = crossesl.pop(0) braid.append(c[3]*min(map(P, [c[1] + 1, c[2] + 1]))) P = G(Permutation([(c[1] + 1, c[2] + 1)]))*P crossesl = [(P(c[2]+1) - P(c[1]+1),c[1],c[2],c[3]) for c in crossesl] B = BraidGroup(len(L)) return B(braid)
def from_table(self, n, k): """ Return a knot from its index in the Rolfsen table. INPUT: - ``n`` -- the crossing number - ``k`` -- a positive integer OUTPUT: the knot `K_{n,k}` in the Rolfsen table EXAMPLES:: sage: K1 = Knots().from_table(6,3); K1 Knot represented by 6 crossings sage: K1.alexander_polynomial() t^-2 - 3*t^-1 + 5 - 3*t + t^2 sage: K2 = Knots().from_table(8,4); K2 Knot represented by 9 crossings sage: K2.determinant() 19 sage: K2.signature() 2 sage: K3 = Knots().from_table(10,56); K3 Knot represented by 11 crossings sage: K3.jones_polynomial() t^10 - 3*t^9 + 6*t^8 - 9*t^7 + 10*t^6 - 11*t^5 + 10*t^4 - 7*t^3 + 5*t^2 - 2*t + 1 sage: K4 = Knots().from_table(10,100) sage: K4.genus() 4 TESTS:: sage: Knots().from_table(6,6) Traceback (most recent call last): ... ValueError: not found in the knot table sage: Knots().from_table(12,6) Traceback (most recent call last): ... ValueError: more than 10 crossings, not in the knot table REFERENCES: - KnotAtlas, http://katlas.math.toronto.edu/wiki/The_Rolfsen_Knot_Table """ if n > 10: raise ValueError('more than 10 crossings, not in the knot table') from sage.groups.braid import BraidGroup if (n, k) in small_knots_table: m, word = small_knots_table[(n, k)] G = BraidGroup(m) return Knot(G(word)) else: raise ValueError('not found in the knot table')
def braid_from_piecewise(strands): """ Compute the braid corresponding to the piecewise linear curves strands. strands is a list whose elements are a list of pairs (x,y), where x is a real number between 0 and 1, and y is a complex number. INPUT: - A list of lists of tuples (t, c), where t is a number bewteen 0 and 1, and c is a complex number. OUTPUT: The braid formed by the piecewise linear strands. EXAMPLES:: sage: paths = [[(0, I), (0.2, -1 - 0.5*I), (0.8, -1), (1, -I)], [(0, -1), (0.5, -I), (1, 1)], [(0, 1), (0.5, 1 + I), (1, I)]] sage: braid_from_piecewise(paths) s0*s1 """ L = strands i = min([L[k][1][0] for k in range(len(L))]) totalpoints = [[[a[0][1].real(), a[0][1].imag()]] for a in L] indices = [1 for a in range(len(L))] while i < 1: for j in range(len(L)): if L[j][indices[j]][0] > i: xaux = L[j][indices[j] - 1][1] yaux = L[j][indices[j]][1] aaux = L[j][indices[j] - 1][0] baux = L[j][indices[j]][0] interpola = xaux + (yaux - xaux) * (i - aaux) / (baux - aaux) totalpoints[j].append([interpola.real(), interpola.imag()]) else: totalpoints[j].append( [L[j][indices[j]][1].real(), L[j][indices[j]][1].imag()]) indices[j] = indices[j] + 1 i = min([L[k][indices[k]][0] for k in range(len(L))]) for j in range(len(L)): totalpoints[j].append([L[j][-1][1].real(), L[j][-1][1].imag()]) braid = [] G = SymmetricGroup(len(totalpoints)) for i in range(len(totalpoints[0]) - 1): l1 = [totalpoints[j][i] for j in range(len(L))] l2 = [totalpoints[j][i + 1] for j in range(len(L))] M = [[l1[s], l2[s]] for s in range(len(l1))] M.sort() l1 = [a[0] for a in M] l2 = [a[1] for a in M] cruces = [] for j in range(len(l2)): for k in range(j): if l2[j] < l2[k]: t = (l1[j][0] - l1[k][0]) / (l2[k][0] - l1[k][0] + l1[j][0] - l2[j][0]) s = cmp(l1[k][1] * (1 - t) + t * l2[k][1], l1[j][1] * (1 - t) + t * l2[j][1]) cruces.append([t, k, j, -s]) if len(cruces) > 0: cruces.sort() P = G(Permutation([])) while cruces: # we select the crosses in the same t crucesl = [c for c in cruces if c[0] == cruces[0][0]] crossesl = [(P(c[2] + 1) - P(c[1] + 1), c[1], c[2], c[3]) for c in crucesl] cruces = cruces[len(crucesl):] while crossesl: crossesl.sort() c = crossesl.pop(0) braid.append(c[3] * min(map(P, [c[1] + 1, c[2] + 1]))) P = G(Permutation([(c[1] + 1, c[2] + 1)])) * P crossesl = [(P(c[2] + 1) - P(c[1] + 1), c[1], c[2], c[3]) for c in crossesl] B = BraidGroup(len(L)) return B(braid)
def connected_sum(self, other): r""" Return the oriented connected sum of ``self`` and ``other``. .. NOTE:: We give the knots an orientation based upon the braid representation. INPUT: - ``other`` -- a knot OUTPUT: A knot equivalent to the connected sum of ``self`` and ``other``. EXAMPLES:: sage: B = BraidGroup(2) sage: trefoil = Knot(B([1,1,1])) sage: K = trefoil.connected_sum(trefoil); K Knot represented by 7 crossings sage: K.braid() s0^3*s2^3*s1 .. PLOT:: :width: 300 px B = BraidGroup(2) trefoil = Knot(B([1,1,1])) K = trefoil.connected_sum(trefoil) sphinx_plot(K.plot()) :: sage: rev_trefoil = Knot(B([-1,-1,-1])) sage: K = trefoil.connected_sum(rev_trefoil); K Knot represented by 7 crossings sage: K.braid() s0^3*s2^-3*s1 .. PLOT:: :width: 300 px B = BraidGroup(2) t = Knot(B([1,1,1])) tr = Knot(B([-1,-1,-1])) K = t.connected_sum(tr) sphinx_plot(K.plot()) REFERENCES: - :wikipedia:`Connected_sum` """ from sage.groups.braid import BraidGroup b1 = self.braid() b2 = other.braid() b1s = b1.strands() b2s = b2.strands() B = BraidGroup(b1s + b2s) return Knot( B( list(b1.Tietze()) + [(abs(i) + b2s) * Integer(i).sign() for i in b2.Tietze()] + [b1s]))