def SymmetricPresentation(n): r""" Build the Symmetric group of order `n!` as a finitely presented group. INPUT: - ``n`` -- The size of the underlying set of arbitrary symbols being acted on by the Symmetric group of order `n!`. OUTPUT: Symmetric group as a finite presentation, implementation uses GAP to find an isomorphism from a permutation representation to a finitely presented group representation. Due to this fact, the exact output presentation may not be the same for every method call on a constant ``n``. EXAMPLES:: sage: S4 = groups.presentation.Symmetric(4) sage: S4.as_permutation_group().is_isomorphic(SymmetricGroup(4)) True TESTS:: sage: S = [groups.presentation.Symmetric(i) for i in range(1,4)]; S[0].order() 1 sage: S[1].order(), S[2].as_permutation_group().is_isomorphic(DihedralGroup(3)) (2, True) sage: S5 = groups.presentation.Symmetric(5) sage: perm_S5 = S5.as_permutation_group(); perm_S5.is_isomorphic(SymmetricGroup(5)) True sage: groups.presentation.Symmetric(8).order() 40320 """ from sage.groups.perm_gps.permgroup_named import SymmetricGroup from sage.groups.free_group import _lexi_gen n = Integer(n) perm_rep = SymmetricGroup(n) GAP_fp_rep = libgap.Image( libgap.IsomorphismFpGroupByGenerators(perm_rep, perm_rep.gens())) image_gens = GAP_fp_rep.FreeGeneratorsOfFpGroup() name_itr = _lexi_gen() # Python generator object for variable names F = FreeGroup([next(name_itr) for x in perm_rep.gens()]) ret_rls = tuple([ F(rel_word.TietzeWordAbstractWord(image_gens).sage()) for rel_word in GAP_fp_rep.RelatorsOfFpGroup() ]) return FinitelyPresentedGroup(F, ret_rls)
def SymmetricPresentation(n): r""" Build the Symmetric group of order `n!` as a finitely presented group. INPUT: - ``n`` -- The size of the underlying set of arbitrary symbols being acted on by the Symmetric group of order `n!`. OUTPUT: Symmetric group as a finite presentation, implementation uses GAP to find an isomorphism from a permutation representation to a finitely presented group representation. Due to this fact, the exact output presentation may not be the same for every method call on a constant ``n``. EXAMPLES:: sage: S4 = groups.presentation.Symmetric(4) sage: S4.as_permutation_group().is_isomorphic(SymmetricGroup(4)) True TESTS:: sage: S = [groups.presentation.Symmetric(i) for i in range(1,4)]; S[0].order() 1 sage: S[1].order(), S[2].as_permutation_group().is_isomorphic(DihedralGroup(3)) (2, True) sage: S5 = groups.presentation.Symmetric(5) sage: perm_S5 = S5.as_permutation_group(); perm_S5.is_isomorphic(SymmetricGroup(5)) True sage: groups.presentation.Symmetric(8).order() 40320 """ from sage.groups.perm_gps.permgroup_named import SymmetricGroup from sage.groups.free_group import _lexi_gen n = Integer(n) perm_rep = SymmetricGroup(n) GAP_fp_rep = libgap.Image(libgap.IsomorphismFpGroupByGenerators(perm_rep, perm_rep.gens())) image_gens = GAP_fp_rep.FreeGeneratorsOfFpGroup() name_itr = _lexi_gen() # Python generator object for variable names F = FreeGroup([next(name_itr) for x in perm_rep.gens()]) ret_rls = tuple( [F(rel_word.TietzeWordAbstractWord(image_gens).sage()) for rel_word in GAP_fp_rep.RelatorsOfFpGroup()] ) return FinitelyPresentedGroup(F, ret_rls)
def CyclicCodeFromGeneratingPolynomial(n,g,ignore=True): r""" If g is a polynomial over GF(q) which divides `x^n-1` then this constructs the code "generated by g" (ie, the code associated with the principle ideal `gR` in the ring `R = GF(q)[x]/(x^n-1)` in the usual way). The option "ignore" says to ignore the condition that (a) the characteristic of the base field does not divide the length (the usual assumption in the theory of cyclic codes), and (b) `g` must divide `x^n-1`. If ignore=True, instead of returning an error, a code generated by `gcd(x^n-1,g)` is created. EXAMPLES:: sage: P.<x> = PolynomialRing(GF(3),"x") sage: g = x-1 sage: C = codes.CyclicCodeFromGeneratingPolynomial(4,g); C Linear code of length 4, dimension 3 over Finite Field of size 3 sage: P.<x> = PolynomialRing(GF(4,"a"),"x") sage: g = x^3+1 sage: C = codes.CyclicCodeFromGeneratingPolynomial(9,g); C Linear code of length 9, dimension 6 over Finite Field in a of size 2^2 sage: P.<x> = PolynomialRing(GF(2),"x") sage: g = x^3+x+1 sage: C = codes.CyclicCodeFromGeneratingPolynomial(7,g); C Linear code of length 7, dimension 4 over Finite Field of size 2 sage: C.generator_matrix() [1 1 0 1 0 0 0] [0 1 1 0 1 0 0] [0 0 1 1 0 1 0] [0 0 0 1 1 0 1] sage: g = x+1 sage: C = codes.CyclicCodeFromGeneratingPolynomial(4,g); C Linear code of length 4, dimension 3 over Finite Field of size 2 sage: C.generator_matrix() [1 1 0 0] [0 1 1 0] [0 0 1 1] On the other hand, CyclicCodeFromPolynomial(4,x) will produce a ValueError including a traceback error message: "`x` must divide `x^4 - 1`". You will also get a ValueError if you type :: sage: P.<x> = PolynomialRing(GF(4,"a"),"x") sage: g = x^2+1 followed by CyclicCodeFromGeneratingPolynomial(6,g). You will also get a ValueError if you type :: sage: P.<x> = PolynomialRing(GF(3),"x") sage: g = x^2-1 sage: C = codes.CyclicCodeFromGeneratingPolynomial(5,g); C Linear code of length 5, dimension 4 over Finite Field of size 3 followed by C = CyclicCodeFromGeneratingPolynomial(5,g,False), with a traceback message including "`x^2 + 2` must divide `x^5 - 1`". """ P = g.parent() x = P.gen() F = g.base_ring() p = F.characteristic() if not(ignore) and p.divides(n): raise ValueError('The characteristic %s must not divide %s'%(p,n)) if not(ignore) and not(g.divides(x**n-1)): raise ValueError('%s must divide x^%s - 1'%(g,n)) gn = GCD([g,x**n-1]) d = gn.degree() coeffs = Sequence(gn.list()) r1 = Sequence(coeffs+[0]*(n - d - 1)) Sn = SymmetricGroup(n) s = Sn.gens()[0] # assumes 1st gen of S_n is (1,2,...,n) rows = [permutation_action(s**(-i),r1) for i in range(n-d)] MS = MatrixSpace(F,n-d,n) return LinearCode(MS(rows))
def CyclicCodeFromGeneratingPolynomial(n,g,ignore=True): r""" If g is a polynomial over GF(q) which divides `x^n-1` then this constructs the code "generated by g" (ie, the code associated with the principle ideal `gR` in the ring `R = GF(q)[x]/(x^n-1)` in the usual way). The option "ignore" says to ignore the condition that (a) the characteristic of the base field does not divide the length (the usual assumption in the theory of cyclic codes), and (b) `g` must divide `x^n-1`. If ignore=True, instead of returning an error, a code generated by `gcd(x^n-1,g)` is created. EXAMPLES:: sage: P.<x> = PolynomialRing(GF(3),"x") sage: g = x-1 sage: C = codes.CyclicCodeFromGeneratingPolynomial(4,g); C Linear code of length 4, dimension 3 over Finite Field of size 3 sage: P.<x> = PolynomialRing(GF(4,"a"),"x") sage: g = x^3+1 sage: C = codes.CyclicCodeFromGeneratingPolynomial(9,g); C Linear code of length 9, dimension 6 over Finite Field in a of size 2^2 sage: P.<x> = PolynomialRing(GF(2),"x") sage: g = x^3+x+1 sage: C = codes.CyclicCodeFromGeneratingPolynomial(7,g); C Linear code of length 7, dimension 4 over Finite Field of size 2 sage: C.gen_mat() [1 1 0 1 0 0 0] [0 1 1 0 1 0 0] [0 0 1 1 0 1 0] [0 0 0 1 1 0 1] sage: g = x+1 sage: C = codes.CyclicCodeFromGeneratingPolynomial(4,g); C Linear code of length 4, dimension 3 over Finite Field of size 2 sage: C.gen_mat() [1 1 0 0] [0 1 1 0] [0 0 1 1] On the other hand, CyclicCodeFromPolynomial(4,x) will produce a ValueError including a traceback error message: "`x` must divide `x^4 - 1`". You will also get a ValueError if you type :: sage: P.<x> = PolynomialRing(GF(4,"a"),"x") sage: g = x^2+1 followed by CyclicCodeFromGeneratingPolynomial(6,g). You will also get a ValueError if you type :: sage: P.<x> = PolynomialRing(GF(3),"x") sage: g = x^2-1 sage: C = codes.CyclicCodeFromGeneratingPolynomial(5,g); C Linear code of length 5, dimension 4 over Finite Field of size 3 followed by C = CyclicCodeFromGeneratingPolynomial(5,g,False), with a traceback message including "`x^2 + 2` must divide `x^5 - 1`". """ P = g.parent() x = P.gen() F = g.base_ring() p = F.characteristic() if not(ignore) and p.divides(n): raise ValueError, 'The characteristic %s must not divide %s'%(p,n) if not(ignore) and not(g.divides(x**n-1)): raise ValueError, '%s must divide x^%s - 1'%(g,n) gn = GCD([g,x**n-1]) d = gn.degree() coeffs = Sequence(gn.list()) r1 = Sequence(coeffs+[0]*(n - d - 1)) Sn = SymmetricGroup(n) s = Sn.gens()[0] # assumes 1st gen of S_n is (1,2,...,n) rows = [permutation_action(s**(-i),r1) for i in range(n-d)] MS = MatrixSpace(F,n-d,n) return LinearCode(MS(rows))