def monomial_to_word(elem, verbose=0): assert isinstance(elem, Xsp2_Co1) assert isinstance(verbose, int), verbose if verbose: print("Convert monomial element g of G_x0 to word. g is:") print(elem) a = [] qs_i = elem.qs_t monomial = qs_i.monomial_row_op() if verbose: print_monomial_4096(monomial, explain=True) y = (monomial[12] & 0x7ff) mat24.matrix_from_mod_omega(monomial[1:]) perm = mat24.autpl_to_perm(monomial[1:]) perm = mat24.inv_perm(perm) pi = mat24.perm_to_m24num(perm) if pi: a.append(pi + 0xA0000000) if y: a.append(y + 0xC0000000) a = np.array(a, dtype=np.uint32) if verbose: print("Multiplier is:", MM.from_data(a)) print_monomial_4096(monomial, explain=True) return a
def ref_gen_leech2_reduce_n(v, verbose=0): vtype = gen_leech2_subtype(v) subtype = vtype & 0xf out = [] if subtype & 1: coc = (v ^ mat24.ploop_theta(v >> 12)) & 0xfff syn = mat24.cocode_syndrome(coc) src = mat24.vect_to_list(syn, mat24.bw24(syn)) assert len(src) in [1, 3] lst = [1, 2, 3] if subtype == 3 else [0] apply_perm(v, src, lst, len(src), out) v = gen_leech2_op_atom(v, out[0]) out.append(0xC0000000 + ((v >> 12) & 0x7ff)) v = gen_leech2_op_atom(v, out[1]) out.append(0xB0000000 + ((v >> 13) & 0x800)) elif subtype == 6: gv = (v >> 12) & 0xfff vect = mat24.gcode_to_vect(gv) src = mat24.vect_to_list(vect, mat24.bw24(vect)) assert len(src) == 12 dest = STD_DODECAD if (vtype == 0x36): coc = (v ^ mat24.ploop_theta(v >> 12)) & 0xfff w = mat24.bw24(mat24.cocode_as_subdodecad(coc, gv)) if w & 2: dest = CPL_DODECAD pi = mat24.perm_from_dodecads(dest, src) out.append(0xA0000000 + mat24.perm_to_m24num(pi)) op_y_x(v, TABLE_DODECAD, out) elif subtype in [2, 4]: if vtype == 0x34: find_octad_permutation_odd(v, out) else: find_octad_permutation(v, out) op_y_x(v, TABLE_OCTAD, out) elif subtype in [0, 8]: if ((v & 0x7ff) == 0): out.append(0xA0000000) out.append(0xC0000000) x = 0x800 if v & 0x1800000 == 0x1800000 else 0 out.append(0x90000000 + x) else: syn = mat24.cocode_syndrome(v & 0x7ff, 0) src = mat24.vect_to_list(syn, mat24.bw24(syn)) j = mat24.bw24(syn) & 2 lst, y0 = ([2, 3], 0x200) if j else ([0, 1, 2, 3], 0x400) apply_perm(v, src, lst, len(lst), out) v = gen_leech2_op_atom(v, out[0]) y = y0 if v & 0x800000 else 0 out.append(0xC0000000 + y) v = gen_leech2_op_atom(v, out[1]) x = y0 if v & 0x1000000 else 0 out.append(0xB0000000 + x) else: raise ValueError("Bad subtype " + hex(vtype)) assert len(out) == 3 return vtype, np.array(out, dtype=np.uint32)
def check(self): """Check automorphism for consistency via 'assert' statements ``a.check()`` returns ``a``. """ assert self._perm == mat24.autpl_to_perm(self.rep) assert self._perm_num == mat24.perm_to_m24num(self._perm) assert 0 <= self._perm_num < mat24.MAT24_ORDER assert self._cocode == mat24.autpl_to_cocode(self.rep) return self
def test_mat24lex(ntests=5000, verbose=0): lindex = [] ldata = [] for i, n in enumerate(mat24lex_testcases(ntests)): # Do additional checks for the first few samples test_ref = i < 100 # Compute permutation p with number n using the cython wrapper # mat24.m24num_to_perm() for function mat24_m24num_to_perm() p = mat24.m24num_to_perm(n) # For the first few random test data do: if test_ref: # Check result p against two slow reference implementations p_py_ref = py_mat24_int_to_perm(n) assert p == p_py_ref, (n, p, p_py_ref) p_ref = mat24_int_to_perm(n) assert p == p_ref, (n, p, p_ref) if verbose: print(i, n, p[:10]) # Append pair (n i) to the list 'lindex' and put ldata[i] = p lindex.append((n, i)) ### p[2] = randint(0,23) # This would destroy the order ldata.append(p) # Compute number n1 of permutation p using the cython wrapper # mat24.perm_to_m24num() for function mat24_perm_to_m24num() n1 = mat24.perm_to_m24num(p) # Then n == n1 must hold assert n1 == n, (hex(n), hex(n1), p) # For the first few random test data do: if test_ref: # Check result n1 against a slow reference implementation n1_ref = mat24_perm_to_int(p) assert n1_ref == n, (hex(n), hex(n1_ref), p) # Sort the index list 'lindex' by permutation numbers. lindex.sort() # Let n0 be the first permutation number in 'lindex' and # let p0 be the corresponding permutation. n0, index0 = lindex[0] p0 = ldata[index0] # For all subsequent permutation numbers n1 in the list 'lindex' # let p1 be the corresponding permutation. for n1, index1 in lindex[1:]: p1 = ldata[index1] if n1 > n0: # Check that permutation p1 is greater the the previous # permutation p0 (assuming that n1 is greater than the # previous number n0). assert p1 > p0 elif n1 == n0: # Birthday paradoxon: n1 == n0 may (and will) happen assert p1 == p0 else: raise ValueError("Something is going wrong here") # Update 'previous' number n0 and permutation p0 n0, p0 = n1, p1
def __init__(self, tag, cocode, perm=0): self.tag = tag if isinstance(cocode, Integral): self.cocode = cocode & 0xfff if perm: if isinstance(perm, Integral): self.m24num = perm else: self.m24num = mat24.perm_to_m24num(perm) self.perm = mat24.m24num_to_perm(self.m24num) self.rep = mat24.perm_to_autpl(cocode, self.perm) else: self.m24num = 0 self.perm = mat24.m24num_to_perm(0) self.rep = mat24.cocode_to_autpl(cocode) else: self.rep = cocode self.perm = mat24.autpl_to_perm(self.rep) self.cocode = mat24.autpl_to_cocode(self.rep) self.m24num = mat24.perm_to_m24num(self.perm)
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 apply_perm(v, src, dest, n, log_list, verbose=0): r"""Apply permutation to vector in Leech lattice mod 2. The function computes a permutation :math:`\pi` that maps the entries of the array ``src`` of length ``n`` to the entries of the array ``dest`` (of the same length) in the given order. Let :math:`v_2` be the vector in the Leech lattice mod 2 given by parameter ``v2``. The function returns :math:`v_2 x_\pi`. Parameter ``v2`` and the return value are given in Leech lattice encoding. Parameter ``p_res`` points to an integer where the function stores the element :math:`x_\pi` as a generator of the monster group as as described in file ``mmgroup_generators.h``. That generator is stored with tag ``MMGROUP_ATOM_TAG_IP`` so that we can compute the inverse of :math:`\pi` very efficiently. We compute the inverse of the lowest permutation (in lexical order) that maps ``dest[:n]`` to ``src[:n]``. """ res, p = mat24.perm_from_map(dest[:n], src[:n]) assert res > 0, (res, dest[:n], src[:n]) p_inv = mat24.inv_perm(p) p_num = mat24.perm_to_m24num(p) log_list.append(0xA0000000 + p_num) xd = (v >> 12) & 0xfff xdelta = (v ^ mat24.ploop_theta(xd)) & 0xfff m = mat24.perm_to_matrix(p_inv) xd = mat24.op_gcode_matrix(xd, m) xdelta = mat24.op_cocode_perm(xdelta, p_inv) v_out = (xd << 12) ^ xdelta ^ mat24.ploop_theta(xd) if verbose: print("Apply permutation (mapping v to gcode %s):\n%s" % (hex(mat24.gcode_to_vect(v_out >> 12)), p_inv)) return v_out
def _compute_from_rep(self): self._perm = mat24.autpl_to_perm(self.rep) self._perm_num = mat24.perm_to_m24num(self._perm) self._cocode = mat24.autpl_to_cocode(self.rep)
def autpl_from_obj(d = 0, p = 0, unique = 1): """Try to convert tuple (d, p) to a Parker loop automorphism. Parameter ``d`` decribes a element of the Golay cocode as in the constructor of class ``Cocode``. It may be of type ``int``, ``str`` or an instance of class ``Cocode``. Pt defaults to ``0``. Alternatively, ``d`` may be an instance of class ``AutPL``. In this case, ``p`` must be set to its default value. Parameter ``p`` describes a element of the Mathieu group ``Mat24``. It defaults to the neutral element of ``Mat24``. It may be * An integer encoding the number of a permutation in ``Mat24``. * A list encoding a permutation in the Mathieu group ``Mat24``. * A zip object or a dictionary encodes such a permutation as a mapping. That mapping must contain sufficiently many entries to be unique. * The string 'r' encodes a random permutation in ``Mat24``. If parameter ``unique`` is ``True`` (default), then the parameter ``p`` must either be ``r`` or describe a unique permutation in ``Mat24``. Otherwise lowest possible permutation (in lexicographic order) is taken. The function returns a pair ``(cocode, permutation_number)``. """ if import_pending: complete_import() if isinstance(d, Integral): d_out = int(d) elif isinstance(d, Cocode): d_out = d.value elif isinstance(d, AutPL): d_out, p_out = d._cocode, d._perm_num if p: raise TypeError(ERR_AUTPL_P1 % type(d)) return d_out, p_out elif isinstance(d, str): d_out = Cocode(d).value else: try: f = autpl_conversions[type(d)] except KeyError: raise TypeError(ERR_AUTPL_TYPE % type(d)) if p: raise TypeError(ERR_AUTPL_P1 % type(d)) d_out, p_out = f(d) return d_out, p_out if p == 'r': return d_out, randint(0, MAT24_ORDER - 1) if isinstance(p, Integral): if 0 <= p < MAT24_ORDER: return d_out, int(p) err = "Bad number for permutation in Mathieu group Mat24" raise ValueError(err) if isinstance(p, (list, range)): if mat24.perm_check(p): err = "Permutation is not in Mathieu group M_24" raise ValueError(err) return d_out, mat24.perm_to_m24num(p) if isinstance(p, zip): p = dict(p) if isinstance(p, dict): h1, h2 = [list(t) for t in zip(*p.items())] res, perm = mat24.perm_from_map(h1, h2) if res == 1 or (res > 1 and not unique): return d_out, mat24.perm_to_m24num(perm) if res < 1: err = "Permutation is not in Mathieu group M_24" else: err = "Permutation in Mathieu group M_24 is not unique" raise ValueError(err)