def test_group_op(n_cases): for i in range(n_cases): a1 = AutPL('r', 'r') c, p = randint(0, 0xfff), randint(0, MAT24_ORDER - 1) a2 = AutPL(c, p) assert group(a1) * (group(a2)) == group(a1 * a2) assert group(a1**-1) == group(a1)**-1
def beautify_block_size3(A): """Try to order a matrix with a 3 times 3 block If matrix ``A`` has a 3 times 3 block in rows 0, 1, and 2, then the function checks the diagonal entries with index >= 3. It looks for a set of equal diagonal entries such that the union of the indices of these entries with the set [1,2,3] is an octad. If this is the case then the function returns an element ``g`` that that moves this octad to the first 8 rows and columns. In case of success that element is returned as an instance of class ``MM0``. Otherwise the neutral element in class ``MM0`` is returned. """ bl = blocks(A) if mat24.bw24(bl[0]) != 3: return MM0() blist = [x for x in range(24) if bl[0] & (1 << x)] if (blist != [0, 1, 2]): return MM0() d = defaultdict(list) for b in bl: if b & (b - 1) == 0: index = b.bit_length() - 1 d[A[index, index]].append(index) for lst in d.values(): if len(lst) < 8: try: gc = GCode(blist + lst).bit_list assert len(gc) == 8 except: continue isect = set(blist) & set(gc) #print("isect", isect) if len(isect) == 3: src0 = [x for x in gc if x in isect] src1 = [x for x in gc if not x in isect] dest = range(6) pi = AutPL(0, zip(src0 + src1[:3], dest), 0) return MM0(pi) if len(isect) == 1: src = gc dest = list(range(8)) src0 = [x for x in gc if not x in isect] src1 = [x for x in gc if x in isect] src2 = [x for x in blist if x not in src1] dest = list(range(10)) for i in range(1000): shuffle(src0) shuffle(src2) try: pi = AutPL(0, zip(src0 + src1 + src2, dest)) return MM0(pi) except: pass return MM0()
def beautify_block_size2(A): """Try to order a matrix with 2 times 2 block If matrix ``A`` has 2 times 2 blocks then the function checks the diagonal entries. It looks for a set of equal diagonal entries such that the union of the indices an octad (up to a syndrome of length at most 3). If this is the case then the function returns an element ``g`` that that moves this octad to the first 8 rows and columns. In case of success that element is returned as an instance of class ``MM0``. Otherwise the neutral element in class ``MM0`` is returned. """ bl = blocks(A) if mat24.bw24(bl[0]) != 2: return MM0() blist = [x for x in range(24) if bl[0] & (1 << x)] d = defaultdict(list) for b in bl: if b & (b - 1) == 0: index = b.bit_length() - 1 d[A[index, index]].append(index) for lst in d.values(): if len(lst) <= 8: try: #print(lst) gc = GCode(blist + lst).bit_list #print("GC =", gc) except: continue if set(blist).issubset(gc) and len(gc) == 8: src0 = [x for x in gc if x in blist] src1 = [x for x in gc if x not in blist] dest = list(range(8)) for i in range(1000): shuffle(src1) try: pi = AutPL(0, zip(src0 + src1, dest), 0) return MM0(pi) except: pass if len(set(blist) & set(gc)) == 0 and len(gc) == 8: src0 = gc src1 = blist dest = list(range(10)) for i in range(10000): shuffle(src0) try: pi = AutPL(0, zip(src0 + src1, dest), 0) return MM0(pi) except: pass return MM0()
def test_rand_group_word(n_cases): for i in range(n_cases): aut_cp = AutPL('r', 'r') perm_num = aut_cp.perm_num coc_num = aut_cp.cocode assert aut_cp == AutPL(coc_num, perm_num) assert 0 <= perm_num < mat24.MAT24_ORDER assert 0 <= coc_num < 0x1000 aut_cpe = AutPL('e', 'r') assert aut_cpe.parity == 0 aut_cpe = AutPL('o', 'r') assert aut_cpe.parity == 1
def beautify_large_block(A): """Beautify block matrix ``A`` acting on the Leech lattice The function tries to find a permutation ``g`` in the group ``M_24`` that beautifies a 24 times 24 matrix ``A`` acting on the Leech lattice. The objective of that beautification is to bring the lines and columns of ``A`` coressponding to the largest block in the matrix together. Here a block is a collection of sets of indices. Two indices ``i, j`` belong to the same block if ``A[i,j] != 0``. The function processes the largest block, provided that this block has size at least 3. Element ``g`` is returned and an instance of class ``MM`` corresponding to an element of the monster group. The function returns the neutral element of the monster if beautification is not possible. """ bl = blocks(A)[0] v = GcVector(bl) if len(v) < 3: return MM0() if len(v) <= 5: b = v.bit_list pi = AutPL(0, zip(b, range(len(v))), 0) return MM0('p', pi) try: syn = v.syndrome() except: return MM0() single = (v & syn).bit_list v &= ~syn if len(v) > 8: return MM0() v_list = v.bit_list if len(single): r_list = [7 - x for x in range(len(v_list))] else: r_list = list(range(len(v_list))) if len(single): v_list += single r_list.append(8) for i in range(2000): shuffle(v_list) try: pi = AutPL(0, zip(v_list, r_list), 0) return MM0('p', pi) except: pass return MM0()
def test_group_op(n_cases=100): print("") for i in range(n_cases): p1 = AutPL('r', 'r') p2 = rand_autpl_u7() p2 *= AutPL(Cocode(randint(0, 0xfff))) p12 = (p1 * p2).check() assert p12.rep == mat24.mul_autpl(p1.rep, p2.rep) if i < 1: print(p1, "*", p2, "=", p12) p3 = AutPL('r', 'r') assert (p1 * p2) * p3 == p1 * (p2 * p3) p1i = (p1**-1).check() assert p1 * p1i == p1i * p1 == AutPL()
def rand_pi_mat22(): r"""Generate certain 'random' element of AutPL The function generates a random element ``e`` of the automorphism group ``AutPL`` of the Parker loop, such that the permutation in the Mathieu ``M24`` group corresponding to ``e`` preserves the set ``\{2, 3\}``. """ pi = AutPL('r', 'r') perm = pi.perm l_src = perm[2:4] shuffle(l_src) _, a = mat24.perm_from_map(l_src, [2, 3]) return pi * AutPL('r', a)
def beautify_diagonal_matrix(A): """Try to order a diagonal matrix If matrix ``A`` is diagonal then the function looks for a set of equal diagonal entries that is close to an octad or to a dodecad. If this is the case then the function returns an element ``g`` that that moves this Golay code word to a standard position. In case of success that element is returned as an instance of class ``MM0``. Otherwise the neutral element in class ``MM0`` is returned. """ bl = blocks(A) if mat24.bw24(bl[0]) != 1: return MM0() d = defaultdict(list) for b in bl: if b & (b - 1) == 0: index = b.bit_length() - 1 d[A[index, index]].append(index) singleton = None for lst in d.values(): if len(lst) == 1: singleton = lst for lst in d.values(): dest = list(range(8)) if len(lst) == 8: #print(lst) for i in range(10000): shuffle(lst) try: pi = AutPL(0, zip(lst, dest), 0) #print("yeah") return MM0(pi) except: continue elif len(lst) == 11 and singleton: print("dodecad") DOD = 0xeee111 dest = [i for i in range(24) if (1 << i) & DOD] src = singleton + lst #print(dest) #print(src) #return MM0() pi = mat24.perm_from_dodecads(src, dest) return MM0('p', pi) elif singleton: pi = pi = AutPL(0, zip(singleton, [0]), 0) return MM0('p', pi) return MM0()
def test_autploop(n_cases): for i in range(n_cases): autp = AutPL('r', 'r') g = group(autp) assert g == group([('d', autp.cocode), ('p', autp.perm)]) assert g == group('p', autp) coc, p_num = autp.cocode, autp.perm_num if coc and p_num: assert g.as_tuples() == autp.as_tuples() assert g.as_tuples() == [('d', coc), ('p', p_num)] Coc = Cocode(coc) h1 = range(9, 18) h2 = autp.perm[9:18] assert g == group([('d', Coc), ('p', zip(h1, h2))]) assert g == group([('d', Coc), ('p', dict(zip(h1, h2)))])
def test_parity(): odd, even = Parity(3), Parity(-4) assert odd != even assert Parity(-311) == odd assert int(odd) == 1 assert int(even) == 0 assert (-1)**odd == -1 assert (-1)**even == 1 assert 1**odd == 1**even == 1 assert odd + 1 == odd - 1 == 1 + odd == odd + odd == 7 - odd == even assert odd * odd == -odd == odd assert odd * even == even * odd == 2 * odd == even * 3 == even print("\nPossible parities are:", odd, ",", even) with pytest.raises(ValueError): 2**even with pytest.raises(TypeError): even & even cc1, cc0 = Cocode(0x823), Cocode(0x7ef) assert cc1 + even == even + cc1 == cc0 + odd == odd + cc0 == odd assert cc1 + odd == odd + cc1 == cc0 + even == even + cc0 == even assert odd * cc1 == cc1 * odd == cc1 ccn = Cocode(0) assert even * cc1 == cc1 * even == even * cc0 == cc0 * even == ccn pl = PLoop(0x1234) gc = GCode(pl) assert even * pl == even * gc == GCode(0) assert odd * pl == odd * gc == gc aut = AutPL('e', 'r') assert odd * aut == odd assert even * aut == even
def rand_pi_m22(): r = randint(0, 1) img = [2 + r, 3 - r] + sample(PI22, 3) syn = GcVector(img).syndrome_list() compl = set(range(24)) - set(img + syn) img += sample(syn, 1) + sample(compl, 1) result = AutPL('r', zip(PI7, img)) return result
def beautify_after_signs_10B(A): for i in (5, 6): if A[1, i] < 0: src = [7, 5, 6] if i == 6 else [6, 7, 5] src = [0, 1, 2, 3, 4] + src dest = list(range(7)) #return MM0() return MM0('p', AutPL(0, zip(src, dest), 0)) return MM0()
def map_cooctad(i): """Return a certain perumtation in the Mathieu group M_24 The function returns a permutation in the Mathieu group ``M_24`` that fixes the octad (0,1,...,7) as a set, and the element 8, and that maps i to 9. The permutation is returned as an instance of class AutPL """ if not 9 <= i < 24: raise ValueError("Bad paramter for function map_octad()") if i == 9: return AutPL(0) s0 = [0] + Cocode([0, 8, 9, i, i ^ 1]).syndrome_list() s1 = [x for x in range(8) if not x in s0] src = s0 + s1[:1] + [8, i] dest = [0, 1, 2, 3, 4, 8, 9] return AutPL(0, zip(src, dest), 0)
def analyze_xy(g): t = g.as_tuples() pi_ref = None for tag, i in t: if tag in "xy": print(" ", tag, gc(i)) pi_ref = i if tag in "d": print(" ", "d", cocode(i, pi_ref)) if tag in "p": print(" ", "p", AutPL(0, i).perm)
def sort_single_size3_block(A): """Sort entries of matrix with single 3 times 3 block If matrix ``A`` contains a single 3 times 3 block and some diagonal entries the the function returns a permutation that moves the 3 times 3 block to rows and columns 0, 1, and 2. That permutation is returned as an instance of class ``MM0``. Otherwise the function returns the neutral element in class ``MM0``. """ bl = blocks(A) if mat24.bw24(bl[0]) != 3 or mat24.bw24(bl[1]) != 1: return MM0() blist = [x for x in range(24) if bl[0] & (1 << x)] dlist = sorted([(-A[x, x], x) for x in blist]) src = [x[1] for x in dlist] return MM0('p', AutPL(0, zip(src, [0, 1, 2]), 0))
def find_fourvolution(verbose=0): """Return a certain 'fourvolution' in G_x0 as an element of MM Here a 'fourvolution' is an element v of G_x0 auch that the the image vQ of v in Co_1 is in class 2B of Co_1. Then any preimage of vQ in Co_0 squares to -1. The returned element of v has the following properties: vQ is in y12 * pi * Q, where y12 is an element y_d of N_x0 with, where d is a Golay code word that intersects with each tetrad of the standard sextet in a set of two elements. Here pi is a permutation that centralizes the standard sextet. The standard sextet contains the tetrad [0,1,2,3]. """ global STD_FOURVOLUTION if STD_FOURVOLUTION is not None: return STD_FOURVOLUTION print("Searching for a 'fourvolution' in G_x0...") for i in range(1000000): e = y12 * G('p', 'r') # G([("y",y12), ("p","r")]) order, a = e.half_order() if a == neg and order % 4 == 0: v = (e**(order // 4)) #v = e v.in_G_x0() chi = characters(v) if chi[0] == -13: if is_nice_permutation(get_perm(v)): #print(chi, get_perm(v)) print("found", v) if verbose: print("y part") print(GCode(v.mmdata[0]).bit_list) print("permutation part") print(AutPL(0, v.mmdata[2] & 0xfffffff).perm) STD_FOURVOLUTION = v return v raise ValueError("No suitable fourvolution found")
def beautify_single_block(A): """Beautify matrix ``A`` acting on the Leech lattice using diagonal Here ``A`` is an integer 24 times 2 times matrix acting on the Leech lattice. The function tries to find a permutation ``g`` in the group ``M_24`` that beautifies matrix ``A``. The search for ``g`` is based on the diagonal elements of ``A``. Here we try to group equal diagonal elements together. Element ``g`` is returned and an instance of class ``MM`` corresponding to an element of the monster group. The function returns the neutral element of the monster if beautification is not possible. """ d = defaultdict(list) for i in range(24): d[A[i, i]].append(i) lists = sorted(d.values(), key=lambda x: len(x)) l = lists[0] if 1 <= len(l) <= 5: pi = AutPL(0, zip(l, range(len(l))), 0) return MM0('p', pi) return MM0()
def rand_autpl_u7(): """Generate random Permutation in Mat24 from umbral heptads""" return AutPL(0, zip(rand_u7(), rand_u7()), Cocode("r"))
def trim_cooctad(A): pi = AutPL(0) for i in range(9, 24): if A[8, i]: pi = map_cooctad(i) return MM0('p', pi)
def beautify_permutation(axis): if axis.g_class in pi_dict: pi = AutPL(0, pi_dict[axis.g_class], 0) axis *= MM0('p', pi)
def beautify_case_10B(A): l = sorted([(d, i) for i, d in enumerate(np.diagonal(A[:8, :8]))]) seq = [l[j][1] for j in range(6)] return MM0('p', AutPL(0, zip(seq, range(6)), 0))
def test_create_group_permutation(): for i, (src, dest, num) in enumerate(create_perm_testvectors()): p1 = AutPL(0, zip(src, dest)) p1.check() p1c = p1.copy().check() assert p1c == p1 assert p1.perm_num == num assert p1 == AutPL(0, dict(zip(src, dest))).check() assert p1 == AutPL(0, num).check() assert p1 == AutPL(p1).check() assert p1.cocode == 0 perm = p1.perm assert isinstance(perm, list) assert min(perm) == 0 and max(perm) == 23 for x, y in zip(src, dest): assert perm[x] == y assert p1 == AutPL(0, perm) coc = Cocode(randint(1, 0xfff)) p2 = AutPL(coc, 0) * AutPL(0, perm) p2.check() assert p2 == (AutPL(coc) * AutPL(0, perm)).check() assert p2 == AutPL(coc, perm).check() assert p2 != p1 assert p2.perm_num == p1.perm_num assert p2.cocode == coc.cocode p2c = AutPL(0, perm) * AutPL(coc, 0).check() assert p2.perm_num == p1.perm_num assert Cocode(p2c.cocode) * p2 == coc assert p2 == AutPL(Cocode(p2.cocode), 0) * AutPL(0, p2.perm)
def autpl_testwords(n_cases=50): for i in range(n_cases): if i % 4 == 0: yield rand_autpl_u7() else: yield AutPL('r', 'r')
def test_group_from_perm(n_cases): for i in range(n_cases): h1 = rand_u7() h2 = rand_u7() autp = AutPL(0, zip(h1, h2)) assert autp == AutPL(0, dict(zip(h1, h2))) assert autp.perm == mat24.perm_from_heptads(h1, h2) assert autp.cocode == 0 perm_num = autp.perm_num assert perm_num == mat24.perm_to_m24num(autp.perm) assert autp == AutPL(0, mat24.perm_from_heptads(h1, h2)) assert autp == AutPL(autp) assert autp == AutPL(0, autp.perm_num) assert autp == AutPL(0, zip(h1, h2)) coc_num = randint(1, 0xfff) coc = Cocode(coc_num) assert coc != Cocode(0) assert coc.cocode == coc_num im_coc = coc * autp assert type(im_coc) == type(coc) assert AutPL(im_coc) == AutPL(coc)**autp aut_cp = AutPL(coc) * autp assert aut_cp == AutPL(coc_num, perm_num) if coc_num and perm_num: assert aut_cp.as_tuples() == [('d', coc_num), ('p', perm_num)] assert autp * AutPL(im_coc) == aut_cp assert type(aut_cp) == type(autp) assert aut_cp.perm_num == perm_num assert aut_cp.cocode == coc_num assert Parity(aut_cp) == Parity(coc) assert aut_cp.parity == coc.parity == Parity(coc).ord assert autp == AutPL() * autp == autp * AutPL() with pytest.raises(TypeError): autp * coc with pytest.raises(TypeError): autp * Parity(randint(0, 9)) with pytest.raises(TypeError): autp * randint(2, 9) with pytest.raises(TypeError): randint(2, 9) * autp with pytest.raises(TypeError): autp * PLoop(randint(0, 0x1fff))
def get_perm(m): """Get atom with 'p' tag from monster elemment as permutation""" for tag, n in m.as_tuples(): if tag == 'p': return AutPL(0, n).perm raise ValueError("Permutation in monster element not found")