def display_norm_A(axis): """Display additional information of a 2A axis """ #sample_axes = import_sample_axes() norm_A = axis.norm15 s = "norm(A) = %d (mod 15)" % (norm_A) common = [ a.g_class for a in get_axes().values() if a.norm15 == norm_A and a.g_class != axis.g_class ] if len(common) == 0: return s + "\n" s += ", same norm for class " + " and ".join(map(str, common)) d = 2 if norm_A == 4 else 0 V15 = MMV(15) v = axis.v15 r = mm_op15_eval_A_rank_mod3(v.data, d) rank = r >> 48 v3 = r & 0xffffffffffff s_A = "(A - %d * 1)" % d if d else "A" s += "\nMatrix U = %s (mod 3) has rank %d" % (s_A, rank) if (rank != 23): return s + "\n" v2 = gen_leech3to2_short(v3) if v2: f = "Kernel of U is spanned by a short vector v with A(v) =" a2 = mm_op15_eval_A(v.data, v2) s += "\n%s %d (mod 15)" % (f, a2) if gen_leech3to2_type4(v3): f = "Kernel of U is spanned by a vector of type 4" s += "\n" + f return s + "\n"
def v3_to_v2(v3): """Map type-4 vector from Leech lattice mod 3 to Leech lattice mod 2 The operation of this function is equivalent to function ``py_gen_leech3to2_type4``. But this function is a wrapper for the C function ``gen_leech3to2_type4`` in file ``gen_leech3.c``. """ result = gen_leech3to2_type4(v3) assert result != 0, (str_v3(v3), weight_v3(v3), hex(result)) return result
def find_in_G_x0(w): global err_in_g_x0_py g1i = np.zeros(11, dtype = np.uint32) if mm_op15_norm_A(w) != ORDER_TAGS[OFS_NORM_A]: err_in_g_x0_py = 1 return None w3 = mm_op15_eval_A_rank_mod3(w, ORDER_TAGS[OFS_DIAG_VA]) w3 &= 0xffffffffffff if w3 == 0: err_in_g_x0_py = 2 return None w_type4 = gen_leech3to2_type4(w3) if w_type4 == 0: err_in_g_x0_py = 3 return None wA = np.array(w[:2*24], copy = True) len_g1 = gen_leech2_reduce_type4(w_type4, g1i) assert 0 <= len_g1 <= 6 res = mm_op15_word_tag_A(wA, g1i, len_g1, 1) assert res == 0 perm_num = mm_op15_watermark_A_perm_num( ORDER_TAGS[OFS_WATERMARK_PERM:], wA) if perm_num < 0: err_in_g_x0_py = 4 return None if perm_num > 0: g1i[len_g1] = 0xA0000000 + perm_num res = mm_op15_word_tag_A(wA, g1i[len_g1:], 1, 1) assert res == 0 len_g1 += 1 v_y = mm_aux_mmv_extract_sparse_signs(15, wA, ORDER_TAGS[OFS_TAGS_Y:], 11) if v_y < 0: err_in_g_x0_py = 5 return None y = leech2matrix_solve_eqn(ORDER_TAGS[OFS_SOLVE_Y:], 11, v_y) if y > 0: g1i[len_g1] = 0xC0000000 + y res = mm_op15_word_tag_A(wA, g1i[len_g1:], 1, 1) assert res == 0 len_g1 += 1 if (wA != ORDER_VECTOR[:2*24]).all(): err_in_g_x0_py = 6 return None #print("g1i", g1i[:len_g1]) return g1i[:len_g1]
def make_v71_sample(g71): r"""Compute a vector stabilized by a group element of order 71 Let ``g71`` be an element of the monster group of order 71. The function generates a random vector ``v71`` in the representatoon of the monster modulo 3 and computes the vector ``w = sum(v71 * g71**i for i in range(71))``. ``w`` is stabilized by ``g71``. The function returns triple containing ``v71`` if ``w`` is non-trivial and ``w`` satisfies an additional property described below. Ohterwise the function returns ``None``. The function succeeds with probability about 1/700; so it must be repeated several times. The part of the vector ``w`` labelled with the tag ``A`` corresponds to a symmetric bilinear form over the Leech lattice modulo 3. The function succeeds if that bilinear form correponding to ``w`` has a one-dimesional eigenspace with the eigenvalue ``diag`` containing a type-4 eigenvector in the Leech lattice. In case of success we return the triple ``(v71, gA, diag)``. Here ``gA`` is an element of the subgroup :math:`G_{x0}` of the monster group such that the bilinear form on the Leech lattice corresponding to `w * gA`` has a type-4 eigenvector in the standard frame math:`\Omega`. The values ``v71`` and ``gA`` are returned as strings. ``diag`` is returned as an integer. """ r1 = [("s", x, "r") for x in "XTXTX"] g71 = MM0(g71) v71 = MMV3(r1) w71 = stabilizer_vector(v71, g71, 71) if not w71: return None for diag in range(3): v3 = mm_op3_eval_A_rank_mod3(w71.data, diag) & 0xffffffffffff if v3: v_type4 = gen_leech3to2_type4(v3) if v_type4: return str(v71), gA_from_type4(v_type4), diag return None
def make_order_vector(s_g71, s_v71, s_gA, diag, s_g94, s_v94): v71 = vector_from_data(10, s_v71) g71 = mm_element_from_data(s_g71) w71 = stabilizer_vector(v71, g71, 71) assert w71 is not None w71 *= mm_element_from_data(s_gA) v94 = vector_from_data(6, s_v94) g94 = mm_element_from_data(s_g94) w94 = stabilizer_vector(v94 - v94 * g94, g94**2, 47) assert w94 is not None if not isinstance(diag, int): diag = diag[0] w = w71 + w94 + identity_vector(5 * diag % 15) diag = 0 v3 = mm_op15_eval_A_rank_mod3(w.data, diag) & 0xffffffffffff assert v3 != 0 v_type4 = gen_leech3to2_type4(v3) assert v_type4 == 0x800000 w.reduce() return w
def rand_v3_dict(n): """Create n random vectors and group the according to their weight We create n random vectors in GF(3)^{24}. We return a dictionary ``d`` with the following entries: d[0] counts the vectors not of type 4 in the Leech lattice mod 3. d[w] counts the vectors v of type 4 such that DICT_P[weight(v)] is equal to w. Then the value d[i] should be about P[i] / n. """ d = defaultdict(int) for i in range(n): v3 = rand_v3() v2 = gen_leech3to2_type4(v3) if (v2 == 0): d[0] += 1 else: w = mat24_bw24((v3 | (v3 >> 24)) & 0xffffff) d[DICT_P[w]] += 1 return d
def display_norm_A(i): """Display additional information of a 2A axis """ sample_axes = import_sample_axes() if isinstance(i, str): i = axis_index(i) norm_A = norm_A_mod15(i) s = "norm(A) = %d (mod 15)" % (norm_A) common = [ s for j, s in enumerate(sample_axes.g_classes) if norm_A_mod15(j) == norm_A and j != i ] if len(common) == 0: return s + "\n" s += ", same norm for class " + " and ".join(map(str, common)) d = 2 if norm_A == 4 else 0 V15 = MMV(15) v = V15(sample_axes.v_start) * MM0(sample_axes.g_strings[i]) r = mm_op15_eval_A_rank_mod3(v.data, d) rank = r >> 48 v3 = r & 0xffffffffffff s_A = "(A - %d * 1)" % d if d else "A" s += "\nMatrix U = %s (mod 3) has rank %d" % (s_A, rank) if (rank != 23): return s + "\n" v2 = gen_leech3to2_short(v3) if v2: f = "Kernel of U is spanned by a short vector v with A(v) =" a2 = mm_op15_eval_A(v.data, v2) s += "\n%s %d (mod 15)" % (f, a2) if gen_leech3to2_type4(v3): f = "Kernel of U is spanned by a vector of type 4" s += "\n" + f return s + "\n"