예제 #1
0
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
예제 #2
0
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()
예제 #3
0
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()
예제 #4
0
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
예제 #5
0
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()
예제 #6
0
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()
예제 #7
0
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)
예제 #8
0
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()
예제 #9
0
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)))])    
예제 #10
0
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
예제 #11
0
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
예제 #12
0
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()
예제 #13
0
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)
예제 #14
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)
예제 #15
0
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")
예제 #17
0
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()
예제 #18
0
def rand_autpl_u7():
    """Generate random Permutation in Mat24 from umbral heptads"""
    return AutPL(0, zip(rand_u7(), rand_u7()), Cocode("r"))
예제 #19
0
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)
예제 #20
0
def beautify_permutation(axis):
    if axis.g_class in pi_dict:
        pi = AutPL(0, pi_dict[axis.g_class], 0)
        axis *= MM0('p', pi)
예제 #21
0
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))
예제 #22
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)
예제 #23
0
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')
예제 #24
0
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")