def polygon(n): """ This constructs a polygon with n sides. INPUT: A positive integer n, at least 1. OUTPUT: A closed ribbon graph. EXAMPLE: >>> RibbonGraph.polygon(4) # doctest:+ELLIPSIS <__main__.RibbonGraph object at 0x...> """ if n<1: raise ValueError a = [ ribbon.halfedge() for i in xrange(n) ] b1 = [ ribbon.halfedge() for i in xrange(n) ] b2 = [ ribbon.halfedge() for i in xrange(n) ] for i in xrange(n-1): b1[i].e = b2[i+1] b2[i+1].e = b1[i] b1[n-1].e = b2[0] b2[0].e = b1[n-1] for i in xrange(n): a[i].c = b1[i] b1[i].c = b2[i] b2[i].c = a[i] h = ribbon.justgraph(a+b1+b2) return RibbonGraph(h,a)
def Artin_generator(n,k): """Constructs the Artin generator s_k of n string braif group. INPUT: n a positive integer, k an integer with 0 < |k| < n OUTPUT: A Morphism >>> s1 = Artin_generator(3,1) >>> s2 = Artin_generator(3,2) """ if not 0 < abs(k) < n: raise ValueError # These are also defined in knots.py in_over = ribbon.Features('head','blue',True) in_under = ribbon.Features('head','blue',False) out_over = ribbon.Features('tail','blue',True) out_under = ribbon.Features('tail','blue',False) r = range(n) do = [ ribbon.halfedge() for i in r ] co = [ ribbon.halfedge() for i in r ] for a in do: a.decorations = in_over a.IsI = True for a in co: a.decorations = out_over a.IsI = True for i in r: do[i].c = co[i] co[i].c = do[i] p =abs(k) do[p-1].IsI = False do[p].IsI = False co[p-1].IsI = False co[p].IsI = False do[p-1].c = do[p] do[p].c = co[p] co[p].c = co[p-1] co[p-1].c = do[p-1] if k > 0: do[k-1].decorations = in_over do[k].decorations = in_under co[k-1].decorations = out_under co[k].decorations = out_over elif k < 0: do[p-1].decorations = in_under do[p].decorations = in_over co[p-1].decorations = out_over co[p].decorations = out_under else: raise RuntimeError g = ribbon.justgraph( set(do+co) ) return Morphism(g, do, co)
def vogel_move(f,u,v): # This goes into an infinite loop phi = f.graph.copy() new = phi.codomain a = phi.map[u] b = a.e c = phi.map[v] d = c.e x = [ ribbon.halfedge() for i in range(4) ] for i in range(4): x[i-1].c = x[i] y = [ ribbon.halfedge() for i in range(4) ] for i in range(4): y[i-1].c = y[i] a.e = x[0]; x[0].e = a d.e = x[3]; x[3].e = d b.e = y[1]; y[1].e = b c.e = y[2]; y[2].e = c x[1].e = y[0]; y[0].e = x[1] x[2].e = y[3]; y[3].e = x[2] switch = {'head':'tail','neither':'neither','tail':'head'} ut = a.decorations.directed ot = switch[ut] if False: x[0].decorations._replace(a.decorations.colour) x[1].decorations._replace(c.decorations.colour) x[2].decorations._replace(a.decorations.colour) x[3].decorations._replace(c.decorations.colour) y[0].decorations._replace(d.decorations.colour) y[1].decorations._replace(b.decorations.colour) y[2].decorations._replace(d.decorations.colour) y[3].decorations._replace(b.decorations.colour) for a in x: a.decorations._replace(colour='red') for a in y: a.decorations._replace(colour='red') g = ribbon.justgraph( new.he.union( set(x+y) ) ) u = phi.map[f.outside[0]] outside = [u] s = u.e.c while s != u: outside.append(s) s = s.e.c return LinkDiagram(g,outside)
def vertex(x): """ Constructs a single vertex of valency n. INPUT: A positive integer n, at least 1 or a list of features. OUTPUT: A closed ribbon graph. EXAMPLES: >>> RibbonGraph.vertex(3) # doctest:+ELLIPSIS <__main__.RibbonGraph object at 0x...> """ if isinstance(x, Iterable): n = len(x) else: n = x if n<1: raise ValueError("Not enough points.") a = [ ribbon.halfedge() for i in xrange(n) ] for i in xrange(n-1): a[i].c = a[i+1] a[n-1].c = a[0] if isinstance(x, Iterable): for i, r in zip(xrange(n),x): if not isinstance(r, ribbon.features): raise ValueError a[i].decorations = r h = ribbon.justgraph(a) return RibbonGraph(h,a)
def from_PlanarDiagram(PD): """Produces a LinkDiagram from the planar diagram notation. INPUT: A list or set of 4-tuples OUTPUT: A closed justgraph EXAMPLES: >>> LinkDiagram.from_PlanarDiagram([[1,2,3,4],[4,3,6,5],[2,1,5,6]]) #doctest: +ELLIPSIS <__main__.LinkDiagram object at 0x...> >>> g = LinkDiagram.from_PlanarDiagram([[1,2,3,4],[4,3,6,5],[2,1,5,6]]) >>> [ len(v) for v in g.vertices ] [4, 4, 4] >>> [ len(v) for v in g.edges ] [2, 2, 2, 2, 2, 2] >>> x = [ len(v) for v in g.faces ] >>> x.sort() >>> x [2, 2, 2, 3, 3] >>> x = [ len(v) for v in g.graph.get_orbits( lambda a: a.e.c ) ] >>> x.sort() >>> x [2, 2, 2, 3, 3] """ if not all([ len(x) == 4 for x in PD ]): raise ValueError("Not a valid planar diagram code") for i in range(2*len(PD)): p = [ x for x in PD if i+1 in x ] if len(p) != 2: raise ValueError("Not a valid planar diagram code") D = dict() he = set() for x in PD: a = [ ribbon.halfedge() for i in range(4) ] for i in range(4): a[i-1].c = a[i] D[tuple(x)] = a he = he.union(set(a)) for i in range(2*len(PD)): p = [ x for x in PD if i+1 in x ] a0 = D[tuple(p[0])][p[0].index(i+1)] a1 = D[tuple(p[1])][p[1].index(i+1)] a0.e = a1 a1.e = a0 g = ribbon.justgraph(he) outside = g.get_orbits( lambda a: a.e.c )[0] return LinkDiagram(g,outside)
def map(self): labels = ('VE','VF','EV','EF','FV','FE',) flags = dict([]) for l in labels: for i in range(self.degree): flags[(i,l,)] = ribbon.halfedge() for i in range(self.degree): flags[(i,'VE',)].e = flags[(i,'EV',)] flags[(i,'EV',)].e = flags[(i,'VE',)] flags[(i,'VF',)].e = flags[(i,'FV',)] flags[(i,'FV',)].e = flags[(i,'VF',)] flags[(i,'FE',)].e = flags[(i,'EF',)] flags[(i,'EF',)].e = flags[(i,'FE',)] #flags[(i,'VE',)]).c = flags[(self.sigma[i],'VF',)] flags[(self.sigma[i],'VE',)].c = flags[(i,'VF',)] flags[(i,'EV',)].c = flags[(i,'EF',)] flags[(i,'VF',)].c = flags[(i,'VE',)] flags[(self.phi[i],'FV',)].c = flags[(i,'FE',)] flags[(i,'FE',)].c = flags[(i,'FV',)] #flags[(i,'EF',)].c = flags[(self.alpha[i],'EV',)] flags[(self.alpha[i],'EF',)].c = flags[(i,'EV',)] for i in range(self.degree): flags[(i,'EV',)].decorations = ribbon.Features('neither','red',True) flags[(i,'VE',)].decorations = ribbon.Features('neither','red',True) flags[(i,'FV',)].decorations = ribbon.Features('neither','blue',True) flags[(i,'VF',)].decorations = ribbon.Features('neither','blue',True) flags[(i,'FE',)].decorations = ribbon.Features('neither','green',True) flags[(i,'EF',)].decorations = ribbon.Features('neither','green',True) g = ribbon.justgraph(set(flags.values())) a = self.faces[0] x = flags[(a[0],'FE',)] out = [x] y = x.c while y != x: out.append(y) y = y.c out.reverse() sut = [ flags[(i,'FE',)] for i in a ] + [ flags[(i,'FV',)] for i in a ] if set(sut) != set(out): raise RuntimeError return g, out
def closure(self, bv=None): """Construct the closure of a web. INPUT: A web and a boundary vector. OUTPUT: A closed web. EXAMPLES: >>> RibbonGraph.polygon(5).closure() #doctest: +ELLIPSIS <closedgraph.ClosedGraph object at 0x...> >>> RibbonGraph.polygon(5).closure().graph.count_vertices() [0, 0, 5, 10] """ if bv == None: bv = [1] * len(self.bd) if sum(bv) != len(self.bd): raise ValueError("Boundary vector is not consistent with web.") if len(bv) < 3: raise ValueError("Not enough corners.") C = len(bv) B = len(self.bd) phi = self.jg.copy() he = phi.codomain.he rim = ribbon.Features('neither','black',True) switch = {'head':'tail','neither':'neither','tail':'head'} ci = [ ribbon.halfedge() for i in xrange(C) ] for a in ci: a.decorations = rim co = [ ribbon.halfedge() for i in xrange(C) ] for a in co: a.decorations = rim he = he.union(ci+co) bi = [ ribbon.halfedge() for i in xrange(B) ] for a in bi: a.decorations = rim bo = [ ribbon.halfedge() for i in xrange(B) ] for a in bo: a.decorations = rim bc = [ ribbon.halfedge() for i in xrange(B) ] he = he.union(bi+bo+bc) for i in xrange(C): ci[i].c = co[i] co[i].c = ci[i] nb = [ phi.map[a] for a in self.bd ] for i in xrange(B): bi[i].c = bo[i] bo[i].c = bc[i] bc[i].c = bi[i] bc[i].e = nb[i] nb[i].e = bc[i] for a in bc: f = a.e.decorations a.decorations = ribbon.Features(switch[f.directed],f.colour,True) p = 0 for i, a in enumerate(bv): r = co[i-1] for j in xrange(a): bi[p].e = r r.e = bi[p] r = bo[p] p += 1 r.e = ci[i] ci[i].e = r ng = ribbon.justgraph(he) u = co[0] outside = [u] s = u.e.c while s != u: outside.append(s) s = s.e.c return closedgraph.ClosedGraph(ng, outside)
def from_DT(DT): """Construct a knot diagram from the Dowker-Thistlewaite code. The theory is given in the original paper: Classification of knot projections C. H. Dowker & Morwen B. Thistlewaite Topology and its Applications 16 (1983), 19--31 INPUT: A list of positive even integers OUTPUT: A closed justgraph EXAMPLES: >>> LinkDiagram.from_DT(DT([4,6,2])) #doctest: +ELLIPSIS <__main__.LinkDiagram object at 0x...> >>> LinkDiagram.from_DT(DT([4,6,8,2])) #doctest: +ELLIPSIS <__main__.LinkDiagram object at 0x...> >>> LinkDiagram.from_DT(DT([4,8,10,2,6])) #doctest: +ELLIPSIS <__main__.LinkDiagram object at 0x...> >>> LinkDiagram.from_DT(DT([6,8,10,2,4])) #doctest: +ELLIPSIS <__main__.LinkDiagram object at 0x...> >>> g = LinkDiagram.from_DT(DT([4,6,2])) >>> [ len(v) for v in g.vertices ] [4, 4, 4] >>> [ len(v) for v in g.edges ] [2, 2, 2, 2, 2, 2] >>> x = [ len(v) for v in g.faces ] >>> x.sort() >>> x [2, 2, 2, 3, 3] >>> g = LinkDiagram.from_DT(DT([4,6,8,2])) >>> [ len(v) for v in g.vertices ] [4, 4, 4, 4] >>> [ len(v) for v in g.edges ] [2, 2, 2, 2, 2, 2, 2, 2] >>> x = [ len(v) for v in g.faces ] >>> x.sort() >>> x [2, 2, 3, 3, 3, 3] >>> x = [ len(v) for v in g.graph.get_orbits( lambda a: a.c.e ) ] >>> x.sort() >>> x [2, 2, 3, 3, 3, 3] >>> g = LinkDiagram.from_DT(DT([4,8,10,2,6])) >>> [ len(v) for v in g.vertices ] [4, 4, 4, 4, 4] >>> [ len(v) for v in g.edges ] [2, 2, 2, 2, 2, 2, 2, 2, 2, 2] >>> x = [ len(v) for v in g.faces ] >>> x.sort() >>> x [2, 2, 2, 3, 3, 4, 4] >>> x = [ len(v) for v in g.graph.get_orbits( lambda a: a.c.e ) ] >>> x.sort() >>> x [2, 2, 2, 3, 3, 4, 4] >>> g = LinkDiagram.from_DT(DT([8,10,2,12,4,6])) >>> x = [ len(v) for v in g.vertices ] >>> x.sort() >>> x [4, 4, 4, 4, 4, 4] >>> [ len(v) for v in g.edges ] [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2] >>> x = [ len(v) for v in g.faces ] >>> x.sort() >>> x [2, 2, 2, 3, 3, 3, 4, 5] >>> x = [ len(v) for v in g.graph.get_orbits( lambda a: a.c.e ) ] >>> x.sort() >>> x [2, 2, 2, 3, 3, 3, 4, 5] REFS: http://katlas.org/wiki/DT_%28Dowker-Thistlethwaite%29_Codes """ emb = DT.orientation m = 2 * len(emb) left = [ ribbon.halfedge() for i in range(m) ] right = [ ribbon.halfedge() for i in range(m) ] for i in range(m): left[i].e = right[i-1] right[i-1].e = left[i] for i, k in enumerate(DT.code): a = abs(k)-1 x = [ left[2*i], left[a], right[2*i], right[a] ] if k > 0: x[0].decorations = in_over x[1].decorations = in_under x[2].decorations = out_over x[3].decorations = out_under elif k < 0: x[0].decorations = in_under x[1].decorations = in_over x[2].decorations = out_under x[3].decorations = out_over else: raise ValueError("Not a valid Dowker-Thistlewaite code") if emb[i] == -1: x.reverse() elif emb[i] != 1: raise RuntimeError for i in xrange(4): x[i-1].c = x[i] g = ribbon.justgraph( set(left).union(set(right)) ) outside = g.get_orbits( lambda a: a.e.c )[0] return LinkDiagram(g,outside)