def galois_action_on_embeddings(G_K): K = G_K.number_field() Kgal = G_K.splitting_field() embeddings = K.embeddings(Kgal) # first a shortcut in the case where G_K is normal in S_d since then it doesn't # matter for our application since we only care about the image # of the galois group in S_d d = K.absolute_degree() G_K_roots = TransitiveGroup(d, G_K.transitive_number()) if G_K_roots.is_normal(SymmetricGroup(d)): id_G_K = G_K.Hom(G_K).identity() return G_K, id_G_K, id_G_K, Kgal, embeddings # now for the actual computation permutations = [] for g in G_K.gens(): phi = g.as_hom() g_perm = Permutation( [embeddings.index(phi * emb) + 1 for emb in embeddings]).inverse() permutations.append(g_perm) G_K_emb = PermutationGroup(permutations, canonicalize=False) to_emb = G_K.hom(G_K_emb.gens()) from_emb = G_K_emb.hom(G_K.gens()) return G_K_emb, to_emb, from_emb, Kgal, embeddings
def permute_indices(self, permutation): r""" Return a tensor with indices with permuted indices. INPUT: - ``permutation`` -- permutation that has to be applied to the indices the input should be a ``list`` containing the second line of the permutation in Cauchy notation. OUTPUT: - an instance of ``TensorWithIndices`` whose indices names and place are those of ``self`` but whose components have been permuted with ``permutation``. EXAMPLES:: sage: M = FiniteRankFreeModule(QQ, 3, name='M') sage: e = M.basis('e') sage: a = M.tensor((2,0), name='a') sage: a[:] = [[1,2,3], [4,5,6], [7,8,9]] sage: b = M.tensor((2,0), name='b') sage: b[:] = [[-1,2,-3], [-4,5,6], [7,-8,9]] sage: identity = [0,1] sage: transposition = [1,0] sage: a["ij"].permute_indices(identity) == a["ij"] True sage: a["ij"].permute_indices(transposition)[:] == a[:].transpose() True sage: cycle = [1,2,3,0] # the cyclic permutation sending 0 to 1 sage: (a*b)[0,1,2,0] == (a*b)["ijkl"].permute_indices(cycle)[1,2,0,0] True TESTS:: sage: M = FiniteRankFreeModule(QQ, 3, name='M') sage: e = M.basis('e') sage: a = M.tensor((2,0), name='a') sage: a[:] = [[1,2,3], [4,5,6], [7,8,9]] sage: identity = [0,1] sage: transposition = [1,0] sage: a["ij"].permute_indices(identity) == a["ij"] True sage: a["ij"].permute_indices(transposition)[:] == a[:].transpose() True sage: (a*a)["ijkl"].permute_indices([1,2,3,0])[0,1,2,1] == (a*a)[1,2,1,0] True """ # Decomposition of the permutation of the components of self # into product of swaps given by the method # sage.tensor.modules.comp.Components.swap_adjacent_indices # A swap is determined by 3 distinct integers swap_params = list( combinations(range(self._tensor.tensor_rank() + 1), 3)) # The associated permutation is as follows def swap(param, N): i, j, k = param L = list(range(1, N + 1)) L = L[:i] + L[j:k] + L[i:j] + L[k:] return L # Construction of the permutation group generated by swaps perm_group = PermutationGroup( [swap(param, self._tensor.tensor_rank()) for param in swap_params], canonicalize=False) # Compute a decomposition of the permutation as a product of swaps decomposition_as_string = perm_group( [x + 1 for x in permutation]).word_problem(perm_group.gens(), display=False)[0] if decomposition_as_string != "<identity ...>": decomposition_as_string = [ # Two cases wether the term appear with an exponent or not ("^" in term) * term.split("^") + ("^" not in term) * (term.split("^") + ['1']) for term in decomposition_as_string.replace("x", "").split("*") ] decomposition = [(swap_params[int(x) - 1], int(y)) for x, y in decomposition_as_string] decomposition.reverse( ) # /!\ The symetric group acts on the right by default /!\. else: decomposition = [] # Choice of a basis basis = self._tensor._fmodule._def_basis # Swap of components swaped_components = self._tensor.comp(basis) for swap_param, exponent in decomposition: if exponent > 0: for i in range(exponent): # Apply the swap given by swap_param swaped_components = swaped_components\ .swap_adjacent_indices(*swap_param) elif exponent < 0: for i in range(-exponent): # Apply the opposite of the swap given by swap_param swaped_components = swaped_components\ .swap_adjacent_indices( swap_param[0], swap_param[0] + swap_param[2] - swap_param[1], swap_param[2] ) else: pass result = self.__pos__() result._tensor = self._tensor._fmodule.tensor_from_comp( self._tensor.tensor_type(), swaped_components) return result