Source code for curver.load


import re

import curver

REGEX_IS_SPHERE_BRAID = re.compile(r'SB_(?P<num_strands>\d+)$')

# Based on code by William Worden.

# TODO: 3) Document all of these cases.

[docs]def S_0_n(n): # A triangulation of S_{0,n}. assert n >= 3 # We'll build the following triangulation of S_{0,n}: # # | | | | | # |0 |1 |2 |3 |n-3 # | | | | | # | 2n-4 | 2n-3 | 2n-2 | | 3n-7 # X------X------X------X- ... -X------X # | | | | | # | | | | | # |n-2 |n-1 |n |2n-6 |2n-5 # | | | | | # # Note that the (n-1)st puncture is not shown here and is on the "boundary" of the disk. # There are two families of triangles on the top and the bottom and two exceptional cases: # 1) Top triangles are given by [i, i+2n-4, ~(i+1)] for i in range(0, n-3)], # 2) Bottom triangles are given by [i, ~(i+1), ~(i+n-1)] for i in range(n-2, 2n-5), # 3) Left triangle given by [~0, ~(n-2), ~(2n-4)], and # 4) Right triangle given by [n-3, 3n-7, 2n-5]. T = curver.create_triangulation( [(i, i + 2 * n - 4, ~(i + 1)) for i in range(0, n - 3)] + [(i, ~(i + 1), ~(i + n - 1)) for i in range(n-2, 2*n - 5)] + [(~0, ~(n - 2), ~(2 * n - 4)), (n - 3, 3 * n - 7, 2 * n - 5)] ) # We'll then create an arc connecting the ith to (i+1)st punctures. # Note that the arcs connecting (n-2)nd & (n-1)st and (n-1)st & 0th are special. curves, arcs = dict(), dict() for i in range(n-2): arcs['s_%d' % i] = T.edge_arc(2*n-4+i) arcs['s_%d' % (n-2)] = T.edge_arc(2*n-5) arcs['s_%d' % (n-1)] = T.edge_arc(0) return curver.kernel.MappingClassGroup(curves=curves, arcs=arcs)
[docs]def S_1_n(n): assert n >= 1 curves, arcs = dict(), dict() if n == 1: T = curver.create_triangulation((0, 1, 2), (~0, ~1, ~2)) curves['a_0'] = T.curve_from_cut_sequence([0, 2]) curves['b_0'] = T.curve_from_cut_sequence([0, 1]) else: # n > 1: T = curver.create_triangulation( [(0, 1, 2)] + [(~(1+2*i), 1+2*i+2, 1+2*i+3) for i in range(n-1)] + [(2*n+1, ~(2*n), ~(2*n-1))] + [(2*n+1 + i, ~(2*n-2*i), ~(2*n + i)) for i in range(1, n-1)] + [(~0, ~(3*n-1), ~2)] ) curves['a_0'] = T.curve_from_cut_sequence([0, 1] + [3 + 2*j for j in range(n-1)] + [] + [2*n+1 + j for j in range(n-1)]) curves['b_0'] = T.curve_from_cut_sequence([0, 2]) # The twists obtained by pushing a_0 across the punctures. # Note that if the loop ran with i=0 then it would create p_0 == a_0. for i in range(1, n): curves['p_%d' % i] = T.curve_from_cut_sequence([0, 1] + [3 + 2*j for j in range(n-1-i)] + [2*n + 2 - 2*i] + [2*n+i + j for j in range(n-i)]) # The half-twists that permute the ith and (i+1)st punctures. arcs['s_0'] = T.edge_arc(2*n - 1) for i in range(1, n): arcs['s_%d' % i] = T.edge_arc(2*n + 2 - 2*i) return curver.kernel.MappingClassGroup(curves=curves, arcs=arcs)
[docs]def S_2_n(n): assert n >= 1 curves, arcs = dict(), dict() if n == 1: T = curver.create_triangulation( (0, 1, 2), (~1, 3, 4), (~2, ~3, ~4), (~0, 5, 6), (~5, 7, 8), (~6, ~7, ~8) ) curves['a_0'] = T.curve_from_cut_sequence([1, 2, 3]) curves['a_1'] = T.curve_from_cut_sequence([5, 6, 7]) curves['b_0'] = T.curve_from_cut_sequence([1, 2, 4]) curves['b_1'] = T.curve_from_cut_sequence([5, 6, 8]) curves['c_0'] = T.curve_from_cut_sequence([0, 1, 2, 3, 0, 5, 6, 7]) curves['d_1'] = T([2, 2, 2, 2, 2, 1, 1, 1, 0]) else: # n > 1: T = curver.create_triangulation( [(0, 1, 2), (~1, 3, 4), (~2, ~3, ~4), (~0, 5, 6), (~6, ~(3*n+5), ~8)] + [(~(5+2*i), 5+2*i+2, 5+2*i+3) for i in range(n)] + [(2*n+7, ~(2*n+6), ~(2*n+5))] + [(2*n+7+i, ~(2*n+6 - 2*i), ~(2*n+6+i)) for i in range(1, n-1)] ) curves['a_0'] = T.curve_from_cut_sequence([1, 2, 3]) curves['a_1'] = T.curve_from_cut_sequence([6, 5] + [7 + j*2 for j in range(n)] + [] + [2*n+7 + j for j in range(n-1)]) curves['b_0'] = T.curve_from_cut_sequence([1, 2, 4]) curves['b_1'] = T.curve_from_cut_sequence([5, 6, 8]) curves['c_0'] = T.curve_from_cut_sequence([6, 0, 2, 4, 1, 2, 3, 4, 2, 0, 5] + [7 + j*2 for j in range(n)] + [] + [2*n+7 + j for j in range(n-1)]) curves['d_1'] = T([2, 2, 2, 2, 2, 1, 1, 1, 0] + [1, 0] * (n-1) + [1] * (n-1)) # The twists obtained by pushing a_1 across the punctures. # Note that if the loop ran with i=0 then it would create p_0 == a_1. for i in range(1, n): curves['p_%d' % i] = T.curve_from_cut_sequence([6, 5] + [7 + j*2 for j in range(n-i)] + [2*n + 8 - 2*i] + [2*n+6+i + j for j in range(n-i)]) # The half-twists that permute the ith and (i+1)st punctures. arcs['s_0'] = T.edge_arc(2*n + 5) for i in range(1, n): arcs['s_%d' % i] = T.edge_arc(2*n + 8 - 2*i) return curver.kernel.MappingClassGroup(curves=curves, arcs=arcs)
[docs]def S_3_n(n): assert n >= 1 curves, arcs = dict(), dict() if n == 1: T = curver.create_triangulation( (0, 1, 2), (~1, 3, 4), (~2, ~3, ~4), (5, 6, 7), (~6, 8, 9), (~7, ~8, ~9), (10, 11, 12), (~11, 13, 14), (~12, ~13, ~14), (~0, ~5, ~10) ) curves['a_0'] = T.curve_from_cut_sequence([1, 2, 3]) curves['a_1'] = T.curve_from_cut_sequence([6, 7, 8]) curves['a_2'] = T.curve_from_cut_sequence([11, 12, 13]) curves['b_0'] = T.curve_from_cut_sequence([1, 2, 4]) curves['b_1'] = T.curve_from_cut_sequence([6, 7, 9]) curves['b_2'] = T.curve_from_cut_sequence([11, 12, 14]) curves['c_0'] = T.curve_from_cut_sequence([0, 2, 4, 1, 2, 3, 4, 2, 0, 5, 6, 8, 7, 5]) curves['c_1'] = T.curve_from_cut_sequence([5, 7, 9, 6, 7, 8, 9, 7, 5, 10, 11, 13, 12, 10]) curves['d_1'] = T([2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0]) curves['d_2'] = T([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0]) else: # n > 1: T = curver.create_triangulation( [(0, 1, 2), (~1, 3, 4), (~2, ~3, ~4), (5, 6, 7), (~6, 8, 9), (~7, ~8, ~9)] + [(10, 11, 12), (~11, 13, 14), (~12, ~(3*n+11), ~14)] + [(~(13+2*i), 13+2*i+2, 13+2*i+3) for i in range(n-1)] + [(2*n+13, ~(2*n+12), ~(2*n+11))] + [(2*n+13+i, ~(2*n+12-2*i), ~(2*n+12+i)) for i in range(1, n-1)] + [(~0, ~5, ~10)] ) curves['a_0'] = T.curve_from_cut_sequence([1, 2, 3]) curves['a_1'] = T.curve_from_cut_sequence([6, 7, 8]) curves['a_2'] = T.curve_from_cut_sequence([12, 11] + [13 + j*2 for j in range(n)] + [] + [2*n+13 + j for j in range(n-1)]) curves['b_0'] = T.curve_from_cut_sequence([1, 2, 4]) curves['b_1'] = T.curve_from_cut_sequence([6, 7, 9]) curves['b_2'] = T.curve_from_cut_sequence([11, 12, 14]) curves['c_0'] = T.curve_from_cut_sequence([0, 2, 4, 3, 2, 1, 4, 2, 0, 5, 7, 8, 6, 5]) curves['c_1'] = T.curve_from_cut_sequence([12, 10, 5, 7, 9, 6, 7, 8, 9, 7, 5, 10, 11] + [13 + j*2 for j in range(n)] + [] + [2*n+13 + j for j in range(n-1)]) curves['d_1'] = T([2, 2, 2, 2, 2, 2, 1, 1, 1] + [0] * (3*n + 3)) curves['d_2'] = T([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 0] + [1, 0] * (n-1) + [1] * (n-1)) # The twists obtained by pushing a_2 across the punctures. # Note that if the loop ran with i=0 then it would create p_0 == a_2. for i in range(1, n): curves['p_%d' % i] = T.curve_from_cut_sequence([12, 11] + [13 + j*2 for j in range(n-i)] + [2*n + 14 - 2*i] + [2*n+12+i + j for j in range(n-i)]) # The half-twists that permute the ith and (i+1)st punctures. arcs['s_0'] = T.edge_arc(2*n + 11) for i in range(1, n): arcs['s_%d' % i] = T.edge_arc(2*n + 14 - 2*i) return curver.kernel.MappingClassGroup(curves=curves, arcs=arcs)
[docs]def S_g_n(g, n): assert g >= 4 assert n >= 1 curves, arcs = dict(), dict() if n == 1: T = curver.create_triangulation( # Build the fins using the first 5g edges. [(5*i+0, 5*i+1, 5*i+2) for i in range(g)] + [(~(5*i+1), 5*i+3, 5*i+4) for i in range(g)] + [(~(5*i+2), ~(5*i+3), ~(5*i+4)) for i in range(g)] # Finally triangulate the centre polygon using the last g - 3 edges. + [(~0, ~5, 5*g)] + [(5*g+1+i, ~(5*g+i), ~(5*i+10)) for i in range(g-4)] + [(~(5*g+g-4), ~(5*g-10), ~(5*g-5))] ) # 0, ..., 6g - 4. for i in range(g): curves['a_%d' % i] = T.curve_from_cut_sequence([5*i+1, 5*i+2, 5*i+3]) curves['b_%d' % i] = T.curve_from_cut_sequence([5*i+1, 5*i+2, 5*i+4]) curves['c_%d' % 0] = T.curve_from_cut_sequence([5*0+j for j in [0, 2, 4, 3, 2, 1, 4, 2, 0, 5, 6, 8, 7, 5]]) for i in range(1, g-2): curves['c_%d' % i] = T.curve_from_cut_sequence([5*i+j for j in [0, 2, 4, 3, 2, 1, 4, 2, 0, 5, 6, 8, 7, 5]] + [5*g + i - 1, 5*g + i - 1]) curves['c_%d' % (g-2)] = T.curve_from_cut_sequence([5*(g-2)+j for j in [0, 2, 4, 3, 2, 1, 4, 2, 0, 5, 6, 8, 7, 5]]) for i in range(1, g-1): curves['d_%d' % i] = T([2] + [2] * (5*i) + [1, 1, 1] + [0] * (5*g + 3*n - 7 - 5*i) + [2] * (i-1) + [0] * (1 + g - 3 - i)) curves['d_%d' % (g-1)] = T([2] * (5*g - 4) + [1, 1, 1, 0] + [2]*(g-3)) else: # n > 1: T = curver.create_triangulation( # Build the fins using the first 5g edges. [(5*i+0, 5*i+1, 5*i+2) for i in range(g)] + [(~(5*i+1), 5*i+3, 5*i+4) for i in range(g)] + [(~(5*i+2), ~(5*i+3), ~(5*i+4)) for i in range(g-1)] # Don't forget the last one is special. + [(~(5*(g-1)+2), ~(5*(g-1)+4+(3*n-3)), ~(5*(g-1)+4))] # Now fold to put in the additional punctures using the next 3n - 3 edges. + [(~(5*g-2 + 2*i), 5*g-2 + 2*i + 2, 5*g-2 + 2*i + 3) for i in range(n-1)] + [(5*g-2 + 2*(n-1) + 2, ~(5*g-2 + 2*(n-1) + 1), ~(5*g-2 + 2*(n-1)))] + [(5*g-2 + 2*(n-1) + 2 + i, ~(5*g-2 + 2*(n-1) + 1 - 2*i), ~(5*g-2 + 2*(n-1) + 2 + i - 1)) for i in range(1, n-1)] # Finally triangulate the centre polygon using the last g - 3 edges. + [(~0, ~5, 5*g+3*n-3)] + [(5*g+3*n-3+1+i, ~(5*g+3*n-3+i), ~(5*i+10)) for i in range(g-4)] + [(~(5*g+3*n-3+g-4), ~(5*g-10), ~(5*g-5))] ) for i in range(g-1): curves['a_%d' % i] = T.curve_from_cut_sequence([5*i+1, 5*i+2, 5*i+3]) curves['a_%d' % (g-1)] = T.curve_from_cut_sequence([5*(g-1)+1, 5*(g-1)+2] + [5*(g-1)+3 + j*2 for j in range(n)] + [] + [5*g+2*n-2 + j for j in range(n-1)]) for i in range(g): curves['b_%d' % i] = T.curve_from_cut_sequence([5*i+1, 5*i+2, 5*i+4]) curves['c_%d' % 0] = T.curve_from_cut_sequence([5*0+j for j in [0, 2, 4, 3, 2, 1, 4, 2, 0, 5, 6, 8, 7, 5]]) for i in range(1, g-2): curves['c_%d' % i] = T.curve_from_cut_sequence([5*i+j for j in [0, 2, 4, 3, 2, 1, 4, 2, 0, 5, 6, 8, 7, 5]] + [5*g + 3*n - 3 + i - 1, 5*g + 3*n - 3 + i - 1]) curves['c_%d' % (g-2)] = T.curve_from_cut_sequence([5*(g-2) + j for j in [7, 5, 0, 2, 4, 1, 2, 3, 4, 2, 0, 5, 6]] + [5*(g-1)+3 + j*2 for j in range(n)] + [] + [5*g+2*n-2 + j for j in range(n-1)]) for i in range(1, g-1): curves['d_%d' % i] = T([2] + [2] * (5*i) + [1, 1, 1] + [0] * (5*g + 3*n - 7 - 5*i) + [2] * (i-1) + [0] * (1 + g - 3 - i)) curves['d_%d' % (g-1)] = T([2] * (5*g - 4) + [1, 1, 1, 0] + [1, 0]*(n-1) + [1]*(n-1) + [2]*(g-3)) # The twists obtained by pushing a_{g-1} across the punctures. # Note that if the loop ran with i=0 then it would create p_0 == a_{g-1}. for i in range(1, n): curves['p_%d' % i] = T.curve_from_cut_sequence([5*(g-1)+1, 5*(g-1)+2] + [5*(g-1)+3 + j*2 for j in range(n-i)] + [5*g + 2*n - 1 - 2*i] + [5*g+2*n-3+i + j for j in range(n-i)]) # The half-twists that permute the ith and (i+1)st punctures. arcs['s_0'] = T.edge_arc(5*g + 2*n - 4) for i in range(1, n): arcs['s_%d' % i] = T.edge_arc(5*g + 2*n - 1 - 2*i) return curver.kernel.MappingClassGroup(curves=curves, arcs=arcs)
[docs]def load_old(surface): if surface == 'S_0_4': S = load(0, 4) return curver.kernel.MappingClassGroup(arcs={ 'a': S.arcs['s_1'], 'b': S.arcs['s_2'], 'c': S.arcs['s_3'], 'd': S.arcs['s_0'], }) elif surface == 'S_1_1': S = load(1, 1) return curver.kernel.MappingClassGroup(curves={ 'a': S.curves['a_0'], 'b': S.curves['b_0'], }) elif surface == 'S_1_2': S = load(1, 2) return curver.kernel.MappingClassGroup(curves={ 'a': S.curves['a_0'], 'b': S.curves['b_0'], 'c': S.curves['p_1'], }, arcs={ 'x': S.arcs['s_1'], }) elif surface == 'S_1_2p': S = load(1, 2) return curver.kernel.MappingClassGroup(curves={ 'a': S.curves['a_0'], 'b': S.curves['b_0'], 'c': S.curves['p_0'], }) elif surface == 'S_2_1': S = load(2, 1) return curver.kernel.MappingClassGroup(curves={ 'a': S.curves['b_0'], 'b': S.curves['c_0'], 'c': S.curves['b_1'], 'd': S.curves['a_1'], 'e': S.curves['d_1'], 'f': S.curves['a_0'], }) elif surface == 'S_3_1': S = load(3, 1) return curver.kernel.MappingClassGroup(curves={ 'a': S.curves['b_0'], 'b': S.curves['c_0'], 'c': S.curves['b_1'], 'd': S.curves['c_1'], 'e': S.curves['b_2'], 'f': S.curves['d_2'], 'g': S.curves['a_2'], 'h': S.curves['a_1'], }) elif surface == 'S_4_1': S = load(4, 1) return curver.kernel.MappingClassGroup(curves={ 'a': S.curves['b_0'], 'b': S.curves['c_0'], 'c': S.curves['b_1'], 'd': S.curves['c_1'], 'e': S.curves['b_2'], 'f': S.curves['c_2'], 'g': S.curves['b_3'], 'h': S.curves['d_3'], 'i': S.curves['a_3'], 'j': S.curves['a_2'], }) elif surface == 'S_5_1': S = load(5, 1) return curver.kernel.MappingClassGroup(curves={ 'a': S.curves['b_0'], 'b': S.curves['c_0'], 'c': S.curves['b_1'], 'd': S.curves['c_1'], 'e': S.curves['b_2'], 'f': S.curves['c_2'], 'g': S.curves['b_3'], 'h': S.curves['c_3'], 'i': S.curves['b_4'], 'j': S.curves['d_4'], 'k': S.curves['a_4'], 'l': S.curves['a_3'], }) elif REGEX_IS_SPHERE_BRAID.match(surface): return S_0_n(int(REGEX_IS_SPHERE_BRAID.match(surface).groupdict()['num_strands'])) else: raise ValueError('Unknown surface: %s' % surface)
[docs]def load(*args): ''' Return the requested example MappingClassGroup. The mapping class group can either be specified by: - a pair (g, n) in which case the Lickorish generating set is returned (see Figures 4.5 and 4.10 of [FarbMarg12]_), or - a string 'S_g_n' in which case the corresponding flipper / Twister generating set is returned. ''' if len(args) == 1: # Load an old flipper surface. surface = args[0] return load_old(surface) elif len(args) == 2: # Build Mod(S_{g, n}). g, n = args assert isinstance(g, curver.IntegerType) assert isinstance(n, curver.IntegerType) zeta = 6*g + 3*n - 6 if g < 0 or n < 1 or zeta < 3: raise ValueError('Surface cannot be triangulated') if g == 0: # and n >= 3. return S_0_n(n) elif g == 1: return S_1_n(n) elif g == 2: return S_2_n(n) elif g == 3: return S_3_n(n) else: # g >= 4: return S_g_n(g, n) else: # len(args) > 2: raise ValueError('Expected a string or pair of integers')