Esempio n. 1
0
def griesmer_upper_bound(n, q, d, algorithm=None):
    r"""
    Returns the Griesmer upper bound for number of elements in the
    largest code of minimum distance d in `\GF{q}^n`.
    Wraps GAP's UpperBoundGriesmer.

    EXAMPLES::

        sage: griesmer_upper_bound(10,2,3)
        128
        sage: griesmer_upper_bound(10,2,3,algorithm="gap")  # optional - gap_packages (Guava package)
        128
    """
    if algorithm == "gap":
        #print "calling Guava ..."
        ans = gap.eval("UpperBoundGriesmer(%s,%s,%s)" % (n, d, q))
        return QQ(ans)
    else:
        den = 1
        s = 0
        k = 0
        add = 0
        while s <= n:
            if not (add == 1):
                if d % den == 0:
                    add = int(d / den)
                else:
                    add = int(d / den) + 1
            s = s + add
            den = den * q
            k = k + 1
        return q**(k - 1)
Esempio n. 2
0
def elias_upper_bound(n,q,d,algorithm=None):
    r"""
    Returns the Elias upper bound for number of elements in the largest
    code of minimum distance d in `\GF{q}^n`. Wraps
    GAP's UpperBoundElias.
    
    EXAMPLES::
    
        sage: elias_upper_bound(10,2,3)
        232
        sage: elias_upper_bound(10,2,3,algorithm="gap")  # requires optional GAP package Guava
        232

    """
    r = 1-1/q
    if algorithm=="gap":
        #print "calling Guava ..."
        ans=gap.eval("UpperBoundElias(%s,%s,%s)"%(n,d,q))
        return QQ(ans)
    else:
        def ff(n,d,w,q):
            return r*n*d*q**n/((w**2-2*r*n*w+r*n*d)*volume_hamming(n,q,w));
    def get_list(n,d,q):
        I = []
        for i in range(1,int(r*n)+1):
            if i**2-2*r*n*i+r*n*d>0:
                I.append(i)
            return I
    I = get_list(n,d,q)
    bnd = min([ff(n,d,w,q) for w in I])
    return int(bnd)
Esempio n. 3
0
def plotkin_upper_bound(n, q, d, algorithm=None):
    r"""
    Returns Plotkin upper bound for number of elements in the largest
    code of minimum distance d in `\GF{q}^n`.

    The algorithm="gap" option wraps Guava's UpperBoundPlotkin.

    EXAMPLES::

        sage: plotkin_upper_bound(10,2,3)
        192
        sage: plotkin_upper_bound(10,2,3,algorithm="gap")  # optional - gap_packages (Guava package)
        192
    """
    if algorithm == "gap":
        ans = gap.eval("UpperBoundPlotkin(%s,%s,%s)" % (n, d, q))
        #print "calling Guava ..."
        return QQ(ans)
    else:
        t = 1 - 1 / q
        if (q == 2) and (n == 2 * d) and (d % 2 == 0):
            return 4 * d
        elif (q == 2) and (n == 2 * d + 1) and (d % 2 == 1):
            return 4 * d + 4
        elif d > t * n:
            return int(d / (d - t * n))
        elif d < t * n + 1:
            fact = (d - 1) / t
            if RR(fact) == RR(int(fact)):
                fact = int(fact) + 1
            return int(d / (d - t * fact)) * q**(n - fact)
Esempio n. 4
0
def elias_upper_bound(n, q, d, algorithm=None):
    r"""
    Returns the Elias upper bound for number of elements in the largest
    code of minimum distance d in `\GF{q}^n`. Wraps
    GAP's UpperBoundElias.

    EXAMPLES::

        sage: elias_upper_bound(10,2,3)
        232
        sage: elias_upper_bound(10,2,3,algorithm="gap")  # optional - gap_packages (Guava package)
        232

    """
    r = 1 - 1 / q
    if algorithm == "gap":
        #print "calling Guava ..."
        ans = gap.eval("UpperBoundElias(%s,%s,%s)" % (n, d, q))
        return QQ(ans)
    else:

        def ff(n, d, w, q):
            return r * n * d * q**n / (
                (w**2 - 2 * r * n * w + r * n * d) * volume_hamming(n, q, w))

    def get_list(n, d, q):
        I = []
        for i in range(1, int(r * n) + 1):
            if i**2 - 2 * r * n * i + r * n * d > 0:
                I.append(i)
        return I

    I = get_list(n, d, q)
    bnd = min([ff(n, d, w, q) for w in I])
    return int(bnd)
Esempio n. 5
0
def griesmer_upper_bound(n,q,d,algorithm=None):
    r"""
    Returns the Griesmer upper bound for number of elements in the
    largest code of minimum distance d in `\GF{q}^n`.
    Wraps GAP's UpperBoundGriesmer.
    
    EXAMPLES::
        sage: griesmer_upper_bound(10,2,3)
        128
        sage: griesmer_upper_bound(10,2,3,algorithm="gap")  # requires optional GAP package Guava
        128
    """
    if algorithm=="gap":
        #print "calling Guava ..."
        ans=gap.eval("UpperBoundGriesmer(%s,%s,%s)"%(n,d,q))
        return QQ(ans)
    else:
        den = 1
        s = 0
        k = 0
        add = 0
        while s <= n:
            if not(add == 1):
                if d%den==0:
                    add = int(d/den)
                else: 
                    add = int(d/den)+1
            s = s + add
            den = den * q
            k = k + 1
        return q**(k-1)
Esempio n. 6
0
    def cpi(self, p):
        """
        Returns the centrally primitive idempotent for the symmetric group
        of order n for the irreducible corresponding indexed by the
        partition p.

        EXAMPLES::

            sage: QS3 = SymmetricGroupAlgebra(QQ,3)
            sage: QS3.cpi([2,1])
            2/3*[1, 2, 3] - 1/3*[2, 3, 1] - 1/3*[3, 1, 2]
            sage: QS3.cpi([3])
            1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1]
            sage: QS3.cpi([1,1,1])
            1/6*[1, 2, 3] - 1/6*[1, 3, 2] - 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] - 1/6*[3, 2, 1]
        """
        if p not in partition.Partitions_n(self.n):
            raise TypeError, "p must be a partition of %s" % self.n

        character_table = eval(
            gap.eval("Display(Irr(SymmetricGroup(%d)));" % self.n))

        cpi = self(0)

        np = partition.Partitions_n(self.n).list()
        np.reverse()
        p_index = np.index(p)

        big_coeff = character_table[p_index][0] / factorial(self.n)

        for g in permutation.StandardPermutations_n(self.n):
            cpi += big_coeff * character_table[p_index][np.index(
                g.inverse().cycle_type())] * self(g)

        return cpi
Esempio n. 7
0
def plotkin_upper_bound(n,q,d, algorithm=None):
    r"""
    Returns Plotkin upper bound for number of elements in the largest
    code of minimum distance d in `\GF{q}^n`. 

    The algorithm="gap" option wraps Guava's UpperBoundPlotkin.
    
    EXAMPLES::
        sage: plotkin_upper_bound(10,2,3) 
        192
        sage: plotkin_upper_bound(10,2,3,algorithm="gap")  # requires optional GAP package Guava
        192
    """
    if algorithm=="gap":
        ans=gap.eval("UpperBoundPlotkin(%s,%s,%s)"%(n,d,q))
        #print "calling Guava ..."
        return QQ(ans)
    else:
        t = 1 - 1/q
        if (q==2) and (n == 2*d) and (d%2 == 0):
            return 4*d
        elif (q==2) and (n == 2*d + 1) and (d%2 == 1):
            return 4*d + 4
        elif d > t*n:
            return int(d/( d - t*n))
        elif d < t*n + 1:
            fact = (d-1) / t
            if RR(fact)==RR(int(fact)):
                fact = int(fact) + 1
            return int(d/( d - t * fact)) * q**(n - fact)
Esempio n. 8
0
def codesize_upper_bound(n,d,q,algorithm=None):
    r"""
    This computes the minimum value of the upper bound using the 
    algorithms of Singleton, Hamming, Plotkin and Elias.

    If algorithm="gap" then this returns the best known upper 
    bound `A(n,d)=A_q(n,d)` for the size of a code of length n, 
    minimum distance d over a field of size q. The function first 
    checks for trivial cases (like d=1 or n=d), and if the value 
    is in the built-in table. Then it calculates the minimum value 
    of the upper bound using the algorithms of Singleton, Hamming, 
    Johnson, Plotkin and Elias. If the code is binary, 
    `A(n, 2\ell-1) = A(n+1,2\ell)`, so the function
    takes the minimum of the values obtained from all algorithms for the
    parameters `(n, 2\ell-1)` and `(n+1, 2\ell)`. This
    wraps GUAVA's UpperBound( n, d, q ).
    
    EXAMPLES::
        sage: codesize_upper_bound(10,3,2)
        93
        sage: codesize_upper_bound(10,3,2,algorithm="gap")  # requires optional GAP package Guava
        85

    """
    if algorithm=="gap":
        return int(gap.eval("UpperBound(%s,%s,%s)"%( n, d, q )))
    else:
        eub = elias_upper_bound(n,q,d)
        gub = griesmer_upper_bound(n,q,d)
        hub = hamming_upper_bound(n,q,d)
        pub = plotkin_upper_bound(n,q,d)
        sub = singleton_upper_bound(n,q,d)
        return min([eub,gub,hub,pub,sub])
Esempio n. 9
0
def elias_upper_bound(n,q,d,algorithm=None):
    r"""
    Returns the Elias upper bound.

    Returns the Elias upper bound for number of elements in the largest
    code of minimum distance `d` in `\GF{q}^n`, cf. [HP2003]_.
    If the method is "gap", it wraps GAP's ``UpperBoundElias``. 

    EXAMPLES::

        sage: codes.bounds.elias_upper_bound(10,2,3)
        232
        sage: codes.bounds.elias_upper_bound(10,2,3,algorithm="gap")  # optional - gap_packages (Guava package)
        232
    """
    _check_n_q_d(n, q, d, field_based=False)
    r = 1-1/q
    if algorithm=="gap":
        gap.load_package("guava")
        ans=gap.eval("UpperBoundElias(%s,%s,%s)"%(n,d,q))
        return QQ(ans)
    else:
        def ff(n,d,w,q):
            return r*n*d*q**n/((w**2-2*r*n*w+r*n*d)*volume_hamming(n,q,w));
    def get_list(n,d,q):
        I = []
        for i in range(1,int(r*n)+1):
            if i**2-2*r*n*i+r*n*d>0:
                I.append(i)
        return I
    I = get_list(n,d,q)
    bnd = min([ff(n,d,w,q) for w in I])
    return int(bnd)
Esempio n. 10
0
    def cpi(self, p):
        """
        Returns the centrally primitive idempotent for the symmetric group
        of order n for the irreducible corresponding indexed by the
        partition p.
        
        EXAMPLES::
        
            sage: QS3 = SymmetricGroupAlgebra(QQ,3)
            sage: QS3.cpi([2,1])
            2/3*[1, 2, 3] - 1/3*[2, 3, 1] - 1/3*[3, 1, 2]
            sage: QS3.cpi([3])
            1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1]
            sage: QS3.cpi([1,1,1])
            1/6*[1, 2, 3] - 1/6*[1, 3, 2] - 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] - 1/6*[3, 2, 1]
        """
        if p not in partition.Partitions_n(self.n):
            raise TypeError, "p must be a partition of %s"%self.n

        character_table = eval(gap.eval("Display(Irr(SymmetricGroup(%d)));"%self.n))

        cpi = self(0)

        np = partition.Partitions_n(self.n).list()
        np.reverse()
        p_index = np.index(p)
        
        big_coeff = character_table[p_index][0]/factorial(self.n)

        for g in permutation.StandardPermutations_n(self.n):
            cpi += big_coeff * character_table[p_index][np.index(g.inverse().cycle_type())] * self(g)

        return cpi
Esempio n. 11
0
def RandomLinearCodeGuava(n,k,F):
    r"""
    The method used is to first construct a `k \times n` matrix of the block
    form `(I,A)`, where `I` is a `k \times k` identity matrix and `A` is a
    `k \times (n-k)` matrix constructed using random elements of `F`. Then
    the columns are permuted using a randomly selected element of the symmetric
    group `S_n`.

    INPUT:

    - ``n,k`` -- integers with `n>k>1`.

    OUTPUT:

    Returns a "random" linear code with length `n`, dimension `k` over field `F`.

    EXAMPLES::

        sage: C = codes.RandomLinearCodeGuava(30,15,GF(2)); C      # optional - gap_packages (Guava package)
        Linear code of length 30, dimension 15 over Finite Field of size 2
        sage: C = codes.RandomLinearCodeGuava(10,5,GF(4,'a')); C      # optional - gap_packages (Guava package)
        Linear code of length 10, dimension 5 over Finite Field in a of size 2^2

    AUTHOR: David Joyner (11-2005)
    """
    current_randstate().set_seed_gap()

    q = F.order()
    gap.eval("C:=RandomLinearCode("+str(n)+","+str(k)+", GF("+str(q)+"))")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i,j)),F) for j in range(1,n+1)] for i in range(1,k+1)]
    MS = MatrixSpace(F,k,n)
    return LinearCode(MS(G))
Esempio n. 12
0
def RandomLinearCodeGuava(n,k,F):
    r"""
    The method used is to first construct a `k \times n` matrix of the block
    form `(I,A)`, where `I` is a `k \times k` identity matrix and `A` is a
    `k \times (n-k)` matrix constructed using random elements of `F`. Then
    the columns are permuted using a randomly selected element of the symmetric
    group `S_n`.

    INPUT:
        Integers `n,k`, with `n>k>1`.

    OUTPUT:
        Returns a "random" linear code with length n, dimension k over field F.

    EXAMPLES::
        sage: C = RandomLinearCodeGuava(30,15,GF(2)); C      # optional - gap_packages (Guava package)
        Linear code of length 30, dimension 15 over Finite Field of size 2
        sage: C = RandomLinearCodeGuava(10,5,GF(4,'a')); C      # optional - gap_packages (Guava package)
        Linear code of length 10, dimension 5 over Finite Field in a of size 2^2

    AUTHOR: David Joyner (11-2005)
    """
    current_randstate().set_seed_gap()

    q = F.order()
    gap.eval("C:=RandomLinearCode("+str(n)+","+str(k)+", GF("+str(q)+"))")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i,j)),F) for j in range(1,n+1)] for i in range(1,k+1)]
    MS = MatrixSpace(F,k,n)
    return LinearCode(MS(G))
Esempio n. 13
0
 def cardinality(self):
     """
     EXAMPLES::
     
         sage: S = [1,2,3,4,5]
         sage: UnorderedTuples(S,2).cardinality()
         15
     """
     ans=gap.eval("NrUnorderedTuples(%s,%s)"%(self._index_list,ZZ(self.k)))
     return ZZ(ans)
Esempio n. 14
0
File: tuple.py Progetto: Babyll/sage
    def cardinality(self):
        """
        EXAMPLES::

            sage: S = [1,2,3,4,5]
            sage: UnorderedTuples(S,2).cardinality()
            15
        """
        ans=gap.eval("NrUnorderedTuples(%s,%s)"%(self._index_list,ZZ(self.k)))
        return ZZ(ans)
Esempio n. 15
0
def griesmer_upper_bound(n,q,d,algorithm=None):
    r"""
    Returns the Griesmer upper bound.

    Returns the Griesmer upper bound for the number of elements in a
    largest linear code of minimum distance `d` in `\GF{q}^n`, cf. [HP2003]_.
    If the method is "gap", it wraps GAP's ``UpperBoundGriesmer``. 

    The bound states:

    .. MATH::

        `n\geq \sum_{i=0}^{k-1} \lceil d/q^i \rceil.`


    EXAMPLES:

    The bound is reached for the ternary Golay codes::

        sage: codes.bounds.griesmer_upper_bound(12,3,6)
        729
        sage: codes.bounds.griesmer_upper_bound(11,3,5)
        729

    ::

        sage: codes.bounds.griesmer_upper_bound(10,2,3)
        128
        sage: codes.bounds.griesmer_upper_bound(10,2,3,algorithm="gap")  # optional - gap_packages (Guava package)
        128

    TESTS::

        sage: codes.bounds.griesmer_upper_bound(11,3,6)
        243
        sage: codes.bounds.griesmer_upper_bound(11,3,6)
        243
    """
    _check_n_q_d(n, q, d)
    if algorithm=="gap":
        gap.load_package("guava")
        ans=gap.eval("UpperBoundGriesmer(%s,%s,%s)"%(n,d,q))
        return QQ(ans)
    else:
        #To compute the bound, we keep summing up the terms on the RHS
        #until we start violating the inequality.
        from sage.functions.other import ceil
        den = 1
        s = 0
        k = 0
        while s <= n:
            s += ceil(d/den)
            den *= q
            k = k + 1
        return q**(k-1)
Esempio n. 16
0
    def list(self):
        """
        EXAMPLES::

            sage: S = [1,2]
            sage: UnorderedTuples(S,3).list()
            [[1, 1, 1], [1, 1, 2], [1, 2, 2], [2, 2, 2]]
            sage: UnorderedTuples(["a","b","c"],2).list()
            [['a', 'a'], ['a', 'b'], ['a', 'c'], ['b', 'b'], ['b', 'c'], ['c', 'c']]
        """
        ans=gap.eval("UnorderedTuples(%s,%s)"%(self._index_list,ZZ(self.k)))
        return map(lambda l: map(lambda i: self.S[i], l), eval(ans))
Esempio n. 17
0
 def list(self):
     """
     EXAMPLES::
     
         sage: S = [1,2]
         sage: UnorderedTuples(S,3).list()
         [[1, 1, 1], [1, 1, 2], [1, 2, 2], [2, 2, 2]]
         sage: UnorderedTuples(["a","b","c"],2).list()
         [['a', 'a'], ['a', 'b'], ['a', 'c'], ['b', 'b'], ['b', 'c'], ['c', 'c']]
     """
     ans=gap.eval("UnorderedTuples(%s,%s)"%(self._index_list,ZZ(self.k)))
     return map(lambda l: map(lambda i: self.S[i], l), eval(ans))
Esempio n. 18
0
File: tuple.py Progetto: Babyll/sage
    def list(self):
        """
        EXAMPLES::

            sage: S = [1,2]
            sage: UnorderedTuples(S,3).list()
            [[1, 1, 1], [1, 1, 2], [1, 2, 2], [2, 2, 2]]
            sage: UnorderedTuples(["a","b","c"],2).list()
            [['a', 'a'], ['a', 'b'], ['a', 'c'], ['b', 'b'], ['b', 'c'], ['c', 'c']]
        """
        ans=gap.eval("UnorderedTuples(%s,%s)"%(self._index_list,ZZ(self.k)))
        return [[self.S[i] for i in l] for l in eval(ans)]
Esempio n. 19
0
    def cardinality(self):
        """
        Returns the size of combinations(mset,k). IMPLEMENTATION: Wraps
        GAP's NrCombinations.

        EXAMPLES::

            sage: mset = [1,1,2,3,4,4,5]
            sage: Combinations(mset,2).cardinality()
            12
        """
        items = map(self.mset.index, self.mset)
        return ZZ(gap.eval("NrCombinations({},{})".format( items,ZZ(self.k))) )
    def cardinality(self):
        """
        Returns the size of combinations(mset,k). IMPLEMENTATION: Wraps
        GAP's NrCombinations.

        EXAMPLES::

            sage: mset = [1,1,2,3,4,4,5]
            sage: Combinations(mset,2).cardinality()
            12
        """
        items = map(self.mset.index, self.mset)
        return ZZ(gap.eval("NrCombinations(%s,%s)" % (items, ZZ(self.k))))
Esempio n. 21
0
    def list(self):
        """
        EXAMPLES::

            sage: S = [1,2]
            sage: UnorderedTuples(S,3).list()
            [[1, 1, 1], [1, 1, 2], [1, 2, 2], [2, 2, 2]]
            sage: UnorderedTuples(["a","b","c"],2).list()
            [['a', 'a'], ['a', 'b'], ['a', 'c'], ['b', 'b'], ['b', 'c'], ['c', 'c']]
        """
        ans = gap.eval("UnorderedTuples(%s,%s)" %
                       (self._index_list, ZZ(self.k)))
        return [[self.S[i] for i in l] for l in eval(ans)]
Esempio n. 22
0
    def cardinality(self):
        """
        Returns the size of combinations(mset,k). IMPLEMENTATION: Wraps
        GAP's NrCombinations.

        EXAMPLES::

            sage: mset = [1,1,2,3,4,4,5]
            sage: Combinations(mset,2).cardinality()
            12
        """
        items = [self.mset.index(_) for _ in self.mset]
        return ZZ(gap.eval("NrCombinations({},{})".format(items, ZZ(self.k))))
Esempio n. 23
0
    def cpi(self, p):
        """
        Return the centrally primitive idempotent for the symmetric group
        of order `n` corresponding to the irreducible representation
        indexed by the partition ``p``.

        EXAMPLES::

            sage: QS3 = SymmetricGroupAlgebra(QQ,3)
            sage: QS3.cpi([2,1])
            2/3*[1, 2, 3] - 1/3*[2, 3, 1] - 1/3*[3, 1, 2]
            sage: QS3.cpi([3])
            1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1]
            sage: QS3.cpi([1,1,1])
            1/6*[1, 2, 3] - 1/6*[1, 3, 2] - 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] - 1/6*[3, 2, 1]

            sage: QS0 = SymmetricGroupAlgebra(QQ, 0)
            sage: QS0.cpi(Partition([]))
            []

        TESTS::

            sage: QS3.cpi([2,2])
            Traceback (most recent call last):
            ...
            TypeError: p (= [2, 2]) must be a partition of n (= 3)
        """
        if p not in partition.Partitions_n(self.n):
            raise TypeError(
                "p (= {p}) must be a partition of n (= {n})".format(p=p,
                                                                    n=self.n))

        character_table = eval(
            gap.eval("Display(Irr(SymmetricGroup(%d)));" % self.n))

        cpi = self.zero()

        np = partition.Partitions_n(self.n).list()
        np.reverse()
        p_index = np.index(p)

        big_coeff = character_table[p_index][0] / factorial(self.n)

        character_row = character_table[p_index]
        dct = {
            g: big_coeff * character_row[np.index(g.cycle_type())]
            for g in permutation.StandardPermutations_n(self.n)
        }

        return self._from_dict(dct)
Esempio n. 24
0
def BinaryReedMullerCode(r, k):
    r"""
    The binary 'Reed-Muller code' with dimension k and
    order r is a code with length `2^k` and minimum distance `2^k-r`
    (see for example, section 1.10 in [HP]_). By definition, the
    `r^{th}` order binary Reed-Muller code of length `n=2^m`, for
    `0 \leq r \leq m`, is the set of all vectors `(f(p)\ |\ p \in GF(2)^m)`,
    where `f` is a multivariate polynomial of degree at most `r`
    in `m` variables.

    INPUT:

    - ``r, k`` -- positive integers with `2^k>r`.

    OUTPUT:

    Returns the binary 'Reed-Muller code' with dimension `k` and order `r`.

    EXAMPLE::

        sage: C = codes.BinaryReedMullerCode(2,4); C  # optional - gap_packages (Guava package)
        Linear code of length 16, dimension 11 over Finite Field of size 2
        sage: C.minimum_distance()              # optional - gap_packages (Guava package)
        4
        sage: C.generator_matrix()                       # optional - gap_packages (Guava package)
        [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
        [0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1]
        [0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1]
        [0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1]
        [0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]
        [0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1]
        [0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1]
        [0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1]
        [0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1]
        [0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 1]
        [0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1]

    AUTHOR: David Joyner (11-2005)
    """
    F = GF(2)
    gap.load_package("guava")
    gap.eval("C:=ReedMullerCode(" + str(r) + ", " + str(k) + ")")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[
        gfq_gap_to_sage(gap.eval("G[" + str(i) + "][" + str(j) + "]"), F)
        for j in range(1, n + 1)
    ] for i in range(1, k + 1)]
    MS = MatrixSpace(F, k, n)
    return LinearCode(MS(G))
Esempio n. 25
0
def codesize_upper_bound(n,d,q,algorithm=None):
    r"""
    This computes the minimum value of the upper bound using the
    methods of Singleton, Hamming, Plotkin, and Elias.

    If algorithm="gap" then this returns the best known upper
    bound `A(n,d)=A_q(n,d)` for the size of a code of length n,
    minimum distance d over a field of size q. The function first
    checks for trivial cases (like d=1 or n=d), and if the value
    is in the built-in table. Then it calculates the minimum value
    of the upper bound using the algorithms of Singleton, Hamming,
    Johnson, Plotkin and Elias. If the code is binary,
    `A(n, 2\ell-1) = A(n+1,2\ell)`, so the function
    takes the minimum of the values obtained from all algorithms for the
    parameters `(n, 2\ell-1)` and `(n+1, 2\ell)`. This
    wraps GUAVA's (i.e. GAP's package Guava) UpperBound( n, d, q ).

    If algorithm="LP" then this returns the Delsarte (a.k.a. Linear
    Programming) upper bound.

    EXAMPLES::

        sage: codes.bounds.codesize_upper_bound(10,3,2)
        93
        sage: codes.bounds.codesize_upper_bound(24,8,2,algorithm="LP")
        4096
        sage: codes.bounds.codesize_upper_bound(10,3,2,algorithm="gap")  # optional - gap_packages (Guava package)
        85
        sage: codes.bounds.codesize_upper_bound(11,3,4,algorithm=None)
        123361
        sage: codes.bounds.codesize_upper_bound(11,3,4,algorithm="gap")  # optional - gap_packages (Guava package)
        123361
        sage: codes.bounds.codesize_upper_bound(11,3,4,algorithm="LP")
        109226

    """
    if algorithm=="gap":
        gap.load_package('guava')
        return int(gap.eval("UpperBound(%s,%s,%s)"%( n, d, q )))
    if algorithm=="LP":
        return int(delsarte_bound_hamming_space(n,d,q))
    else:
        eub = elias_upper_bound(n,q,d)
        gub = griesmer_upper_bound(n,q,d)
        hub = hamming_upper_bound(n,q,d)
        pub = plotkin_upper_bound(n,q,d)
        sub = singleton_upper_bound(n,q,d)
        return min([eub,gub,hub,pub,sub])
Esempio n. 26
0
def codesize_upper_bound(n, d, q, algorithm=None):
    r"""
    This computes the minimum value of the upper bound using the
    methods of Singleton, Hamming, Plotkin, and Elias.

    If algorithm="gap" then this returns the best known upper
    bound `A(n,d)=A_q(n,d)` for the size of a code of length n,
    minimum distance d over a field of size q. The function first
    checks for trivial cases (like d=1 or n=d), and if the value
    is in the built-in table. Then it calculates the minimum value
    of the upper bound using the algorithms of Singleton, Hamming,
    Johnson, Plotkin and Elias. If the code is binary,
    `A(n, 2\ell-1) = A(n+1,2\ell)`, so the function
    takes the minimum of the values obtained from all algorithms for the
    parameters `(n, 2\ell-1)` and `(n+1, 2\ell)`. This
    wraps GUAVA's (i.e. GAP's package Guava) UpperBound( n, d, q ).

    If algorithm="LP" then this returns the Delsarte (a.k.a. Linear
    Programming) upper bound.

    EXAMPLES::

        sage: codes.bounds.codesize_upper_bound(10,3,2)
        93
        sage: codes.bounds.codesize_upper_bound(24,8,2,algorithm="LP")
        4096
        sage: codes.bounds.codesize_upper_bound(10,3,2,algorithm="gap")  # optional - gap_packages (Guava package)
        85
        sage: codes.bounds.codesize_upper_bound(11,3,4,algorithm=None)
        123361
        sage: codes.bounds.codesize_upper_bound(11,3,4,algorithm="gap")  # optional - gap_packages (Guava package)
        123361
        sage: codes.bounds.codesize_upper_bound(11,3,4,algorithm="LP")
        109226

    """
    if algorithm == "gap":
        gap.load_package('guava')
        return int(gap.eval("UpperBound(%s,%s,%s)" % (n, d, q)))
    if algorithm == "LP":
        return int(delsarte_bound_hamming_space(n, d, q))
    else:
        eub = elias_upper_bound(n, q, d)
        gub = griesmer_upper_bound(n, q, d)
        hub = hamming_upper_bound(n, q, d)
        pub = plotkin_upper_bound(n, q, d)
        sub = singleton_upper_bound(n, q, d)
        return min([eub, gub, hub, pub, sub])
Esempio n. 27
0
def BinaryReedMullerCode(r,k):
    r"""
    The binary 'Reed-Muller code' with dimension k and
    order r is a code with length `2^k` and minimum distance `2^k-r`
    (see for example, section 1.10 in [HP]_). By definition, the
    `r^{th}` order binary Reed-Muller code of length `n=2^m`, for
    `0 \leq r \leq m`, is the set of all vectors `(f(p)\ |\ p \\in GF(2)^m)`,
    where `f` is a multivariate polynomial of degree at most `r`
    in `m` variables.

    INPUT:

    - ``r, k`` -- positive integers with `2^k>r`.

    OUTPUT:

    Returns the binary 'Reed-Muller code' with dimension `k` and order `r`.

    EXAMPLE::

        sage: C = codes.BinaryReedMullerCode(2,4); C  # optional - gap_packages (Guava package)
        Linear code of length 16, dimension 11 over Finite Field of size 2
        sage: C.minimum_distance()              # optional - gap_packages (Guava package)
        4
        sage: C.gen_mat()                       # optional - gap_packages (Guava package)
        [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
        [0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1]
        [0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1]
        [0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1]
        [0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]
        [0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1]
        [0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1]
        [0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1]
        [0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1]
        [0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 1]
        [0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1]

    AUTHOR: David Joyner (11-2005)
    """
    F = GF(2)
    gap.load_package("guava")
    gap.eval("C:=ReedMullerCode("+str(r)+", "+str(k)+")")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[gfq_gap_to_sage(gap.eval("G["+str(i)+"]["+str(j)+"]"),F) for j in range(1,n+1)] for i in range(1,k+1)]
    MS = MatrixSpace(F,k,n)
    return LinearCode(MS(G))
Esempio n. 28
0
    def cpi(self, p):
        """
        Return the centrally primitive idempotent for the symmetric group
        of order `n` corresponding to the irreducible representation
        indexed by the partition ``p``.

        EXAMPLES::

            sage: QS3 = SymmetricGroupAlgebra(QQ,3)
            sage: QS3.cpi([2,1])
            2/3*[1, 2, 3] - 1/3*[2, 3, 1] - 1/3*[3, 1, 2]
            sage: QS3.cpi([3])
            1/6*[1, 2, 3] + 1/6*[1, 3, 2] + 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] + 1/6*[3, 2, 1]
            sage: QS3.cpi([1,1,1])
            1/6*[1, 2, 3] - 1/6*[1, 3, 2] - 1/6*[2, 1, 3] + 1/6*[2, 3, 1] + 1/6*[3, 1, 2] - 1/6*[3, 2, 1]

            sage: QS0 = SymmetricGroupAlgebra(QQ, 0)
            sage: QS0.cpi(Partition([]))
            []

        TESTS::

            sage: QS3.cpi([2,2])
            Traceback (most recent call last):
            ...
            TypeError: p (= [2, 2]) must be a partition of n (= 3)
        """
        if p not in partition.Partitions_n(self.n):
            raise TypeError("p (= {p}) must be a partition of n (= {n})".format(p=p, n=self.n))

        character_table = eval(gap.eval("Display(Irr(SymmetricGroup(%d)));"%self.n))

        cpi = self.zero()

        np = partition.Partitions_n(self.n).list()
        np.reverse()
        p_index = np.index(p)

        big_coeff = character_table[p_index][0] / factorial(self.n)

        character_row = character_table[p_index]
        dct = { g : big_coeff * character_row[np.index(g.cycle_type())]
                for g in permutation.StandardPermutations_n(self.n) }

        return self._from_dict(dct)
Esempio n. 29
0
def QuasiQuadraticResidueCode(p):
    r"""
    A (binary) quasi-quadratic residue code (or QQR code), as defined by
    Proposition 2.2 in [BM]_, has a generator matrix in the block form `G=(Q,N)`.
    Here `Q` is a `p \times p` circulant matrix whose top row
    is `(0,x_1,...,x_{p-1})`, where `x_i=1` if and only if `i`
    is a quadratic residue `\mod p`, and `N` is a `p \times p` circulant
    matrix whose top row is `(0,y_1,...,y_{p-1})`, where `x_i+y_i=1` for all `i`.

    INPUT:

    - ``p`` -- a prime `>2`.

    OUTPUT:

    Returns a QQR code of length `2p`.

    EXAMPLES::

        sage: C = codes.QuasiQuadraticResidueCode(11); C   # optional - gap_packages (Guava package)
        Linear code of length 22, dimension 11 over Finite Field of size 2

    REFERENCES:

    .. [BM] Bazzi and Mitter, {\it Some constructions of codes from group actions}, (preprint
      March 2003, available on Mitter's MIT website).

    .. [Jresidue] D. Joyner, {\it On quadratic residue codes and hyperelliptic curves},
      (preprint 2006)

    These are self-orthogonal in general and self-dual when $p \\equiv 3 \\pmod 4$.

    AUTHOR: David Joyner (11-2005)
    """
    F = GF(2)
    gap.load_package("guava")
    gap.eval("C:=QQRCode(" + str(p) + ")")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[
        gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i, j)), F)
        for j in range(1, n + 1)
    ] for i in range(1, k + 1)]
    MS = MatrixSpace(F, k, n)
    return LinearCode(MS(G))
Esempio n. 30
0
File: guava.py Progetto: drupel/sage
def QuasiQuadraticResidueCode(p):
    r"""
    A (binary) quasi-quadratic residue code (or QQR code), as defined by
    Proposition 2.2 in [BM]_, has a generator matrix in the block form `G=(Q,N)`.
    Here `Q` is a `p \times p` circulant matrix whose top row
    is `(0,x_1,...,x_{p-1})`, where `x_i=1` if and only if `i`
    is a quadratic residue `\mod p`, and `N` is a `p \times p` circulant
    matrix whose top row is `(0,y_1,...,y_{p-1})`, where `x_i+y_i=1` for all `i`.

    INPUT:

    - ``p`` -- a prime `>2`.

    OUTPUT:

    Returns a QQR code of length `2p`.

    EXAMPLES::

        sage: C = codes.QuasiQuadraticResidueCode(11); C   # optional - gap_packages (Guava package)
        Linear code of length 22, dimension 11 over Finite Field of size 2

    REFERENCES:

    .. [BM] Bazzi and Mitter, {\it Some constructions of codes from group actions}, (preprint
      March 2003, available on Mitter's MIT website).

    .. [Jresidue] \D. Joyner, {\it On quadratic residue codes and hyperelliptic curves},
      (preprint 2006)

    These are self-orthogonal in general and self-dual when $p \\equiv 3 \\pmod 4$.

    AUTHOR: David Joyner (11-2005)
    """
    F = GF(2)
    gap.load_package("guava")
    gap.eval("C:=QQRCode(" + str(p) + ")")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i, j)), F)
          for j in range(1, n + 1)] for i in range(1, k + 1)]
    MS = MatrixSpace(F, k, n)
    return LinearCode(MS(G))
Esempio n. 31
0
def QuasiQuadraticResidueCode(p):
    r"""
    A (binary) quasi-quadratic residue code (or QQR code), as defined by
    Proposition 2.2 in [BM2003]_, has a generator matrix in the block form `G=(Q,N)`.
    Here `Q` is a `p \times p` circulant matrix whose top row
    is `(0,x_1,...,x_{p-1})`, where `x_i=1` if and only if `i`
    is a quadratic residue `\mod p`, and `N` is a `p \times p` circulant
    matrix whose top row is `(0,y_1,...,y_{p-1})`, where `x_i+y_i=1` for all `i`.

    INPUT:

    - ``p`` -- a prime `>2`.

    OUTPUT:

    Returns a QQR code of length `2p`.

    EXAMPLES::

        sage: C = codes.QuasiQuadraticResidueCode(11); C   # optional - gap_packages (Guava package)
        [22, 11] linear code over GF(2)

    REFERENCES:

    - [BM2003]_

    - [Joy2006]_

    These are self-orthogonal in general and self-dual when $p \\equiv 3 \\pmod 4$.

    AUTHOR: David Joyner (11-2005)
    """
    F = GF(2)
    gap.load_package("guava")
    gap.eval("C:=QQRCode(" + str(p) + ")")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[
        gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i, j)), F)
        for j in range(1, n + 1)
    ] for i in range(1, k + 1)]
    MS = MatrixSpace(F, k, n)
    return LinearCode(MS(G))
Esempio n. 32
0
def QuasiQuadraticResidueCode(p):
    r"""
    A (binary) quasi-quadratic residue code (or QQR code).

    Follows the definition of Proposition 2.2 in [BM]. The code has a generator
    matrix in the block form `G=(Q,N)`. Here `Q` is a `p \times p` circulant
    matrix whose top row is `(0,x_1,...,x_{p-1})`, where `x_i=1` if and only if
    `i` is a quadratic residue `\mod p`, and `N` is a `p \times p` circulant
    matrix whose top row is `(0,y_1,...,y_{p-1})`, where `x_i+y_i=1` for all
    `i`.

    INPUT:

    - ``p`` -- a prime `>2`.

    OUTPUT:

    Returns a QQR code of length `2p`.

    EXAMPLES::

        sage: C = codes.QuasiQuadraticResidueCode(11); C   # optional - gap_packages (Guava package)
        [22, 11] linear code over GF(2)

    These are self-orthogonal in general and self-dual when $p \\equiv 3 \\pmod 4$.

    AUTHOR: David Joyner (11-2005)
    """
    if not is_package_installed('gap_packages'):
        raise PackageNotFoundError('gap_packages')
    F = GF(2)
    gap.load_package("guava")
    gap.eval("C:=QQRCode(" + str(p) + ")")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i, j)), F)
          for j in range(1, n + 1)] for i in range(1, k + 1)]
    MS = MatrixSpace(F, k, n)
    return LinearCode(MS(G))
Esempio n. 33
0
def elias_upper_bound(n, q, d, algorithm=None):
    r"""
    Returns the Elias upper bound.

    Returns the Elias upper bound for number of elements in the largest
    code of minimum distance `d` in `\GF{q}^n`, cf. [HP2003]_.
    If the method is "gap", it wraps GAP's ``UpperBoundElias``.

    EXAMPLES::

        sage: codes.bounds.elias_upper_bound(10,2,3)
        232
        sage: codes.bounds.elias_upper_bound(10,2,3,algorithm="gap")  # optional - gap_packages (Guava package)
        232
    """
    _check_n_q_d(n, q, d, field_based=False)
    r = 1 - 1 / q
    if algorithm == "gap":
        gap.load_package("guava")
        ans = gap.eval("UpperBoundElias(%s,%s,%s)" % (n, d, q))
        return QQ(ans)
    else:

        def ff(n, d, w, q):
            return r * n * d * q**n / (
                (w**2 - 2 * r * n * w + r * n * d) * volume_hamming(n, q, w))

    def get_list(n, d, q):
        I = []
        for i in range(1, int(r * n) + 1):
            if i**2 - 2 * r * n * i + r * n * d > 0:
                I.append(i)
        return I

    I = get_list(n, d, q)
    bnd = min([ff(n, d, w, q) for w in I])
    return int(bnd)
Esempio n. 34
0
def RandomLinearCodeGuava(n, k, F):
    r"""
    The method used is to first construct a `k \times n` matrix of the block
    form `(I,A)`, where `I` is a `k \times k` identity matrix and `A` is a
    `k \times (n-k)` matrix constructed using random elements of `F`. Then
    the columns are permuted using a randomly selected element of the symmetric
    group `S_n`.

    INPUT:

    - ``n,k`` -- integers with `n>k>1`.

    OUTPUT:

    Returns a "random" linear code with length `n`, dimension `k` over field `F`.

    EXAMPLES::

        sage: C = codes.RandomLinearCodeGuava(30,15,GF(2)); C      # optional - gap_packages (Guava package)
        [30, 15] linear code over GF(2)
        sage: C = codes.RandomLinearCodeGuava(10,5,GF(4,'a')); C      # optional - gap_packages (Guava package)
        [10, 5] linear code over GF(4)

    AUTHOR: David Joyner (11-2005)
    """
    current_randstate().set_seed_gap()

    q = F.order()
    if not is_package_installed('gap_packages'):
        raise PackageNotFoundError('gap_packages')
    gap.load_package("guava")
    gap.eval("C:=RandomLinearCode("+str(n)+","+str(k)+", GF("+str(q)+"))")
    gap.eval("G:=GeneratorMat(C)")
    k = int(gap.eval("Length(G)"))
    n = int(gap.eval("Length(G[1])"))
    G = [[gfq_gap_to_sage(gap.eval("G[%s][%s]" % (i, j)), F)
          for j in range(1, n + 1)] for i in range(1, k + 1)]
    MS = MatrixSpace(F, k, n)
    return LinearCode(MS(G))
Esempio n. 35
0
def plotkin_upper_bound(n,q,d, algorithm=None):
    r"""
    Returns the Plotkin upper bound.

    Returns the Plotkin upper bound for the number of elements in a largest
    code of minimum distance `d` in `\GF{q}^n`.
    More precisely this is a generalization of Plotkin's result for `q=2`
    to bigger `q` due to Berlekamp.

    The ``algorithm="gap"`` option wraps Guava's ``UpperBoundPlotkin``.

    EXAMPLES::

        sage: codes.bounds.plotkin_upper_bound(10,2,3)
        192
        sage: codes.bounds.plotkin_upper_bound(10,2,3,algorithm="gap")  # optional - gap_packages (Guava package)
        192
    """
    _check_n_q_d(n, q, d, field_based=False)
    if algorithm=="gap":
        gap.load_package("guava")
        ans=gap.eval("UpperBoundPlotkin(%s,%s,%s)"%(n,d,q))
        return QQ(ans)
    else:
        t = 1 - 1/q
        if (q==2) and (n == 2*d) and (d%2 == 0):
            return 4*d
        elif (q==2) and (n == 2*d + 1) and (d%2 == 1):
            return 4*d + 4
        elif d > t*n:
            return int(d/( d - t*n))
        elif d < t*n + 1:
            fact = (d-1) / t
            if RR(fact)==RR(int(fact)):
                fact = int(fact) + 1
            return int(d/( d - t * fact)) * q**(n - fact)
Esempio n. 36
0
    def as_permutation(self):
        r"""
        Return the element of the permutation group G (isomorphic to the
        abelian group A) associated to a in A.

        EXAMPLES::

            sage: G = AbelianGroup(3,[2,3,4],names="abc"); G
            Multiplicative Abelian group isomorphic to C2 x C3 x C4
            sage: a,b,c=G.gens()
            sage: Gp = G.permutation_group(); Gp
            Permutation Group with generators [(6,7,8,9), (3,4,5), (1,2)]
            sage: a.as_permutation()
            (1,2)
            sage: ap = a.as_permutation(); ap
            (1,2)
            sage: ap in Gp
            True
        """
        from sage.groups.perm_gps.permgroup import PermutationGroup
        from sage.interfaces.all import gap
        G = self.parent()
        invs = list(G.gens_orders())
        s1 = 'A:=AbelianGroup(%s)'%invs
        gap.eval(s1)
        s2 = 'phi:=IsomorphismPermGroup(A)'
        gap.eval(s2)
        s3 = "gens := GeneratorsOfGroup(A)"
        gap.eval(s3)
        L = self.list()
        gap.eval("L1:="+str(L))
        s4 = "L2:=List([1..%s], i->gens[i]^L1[i]);"%len(L)
        gap.eval(s4)
        pg = gap.eval("Image(phi,Product(L2))")
        Gp = G.permutation_group()
        gp = Gp(pg)
        return gp
Esempio n. 37
0
    def __init__(self, ambient, gens, names="f"):
        """
        EXAMPLES::
        
            sage: F = AbelianGroup(5,[30,64,729],names = list("abcde"))
            sage: a,b,c,d,e = F.gens()
            sage: F.subgroup([a^3,b])
            Multiplicative Abelian Group isomorphic to Z x Z, which is the subgroup of
            Multiplicative Abelian Group isomorphic to Z x Z x C30 x C64 x C729
            generated by [a^3, b]            
        
        ::
        
            sage: F.subgroup([c])
            Multiplicative Abelian Group isomorphic to C2 x C3 x C5, which is the subgroup of
            Multiplicative Abelian Group isomorphic to Z x Z x C30 x C64 x C729
            generated by [c]
        
        ::
        
            sage: F.subgroup([a,c])
            Multiplicative Abelian Group isomorphic to C2 x C3 x C5 x
            Z, which is the subgroup of Multiplicative Abelian Group
            isomorphic to Z x Z x C30 x C64 x C729 generated by [a, c]
        
        ::
        
            sage: F.subgroup([a,b*c])
            Multiplicative Abelian Group isomorphic to Z x Z, which is
            the subgroup of Multiplicative Abelian Group isomorphic to
            Z x Z x C30 x C64 x C729 generated by [a, b*c]
        
        ::
        
            sage: F.subgroup([b*c,d])
            Multiplicative Abelian Group isomorphic to C64 x Z, which
            is the subgroup of Multiplicative Abelian Group isomorphic
            to Z x Z x C30 x C64 x C729 generated by [b*c, d]
        
        ::
        
            sage: F.subgroup([a*b,c^6,d],names = list("xyz"))
            Multiplicative Abelian Group isomorphic to C5 x C64 x Z,
            which is the subgroup of Multiplicative Abelian Group
            isomorphic to Z x Z x C30 x C64 x C729 generated by [a*b,
            c^6, d]
        
        ::
        
            sage: H.<x,y,z> = F.subgroup([a*b, c^6, d]); H
            Multiplicative Abelian Group isomorphic to C5 x C64 x Z,
            which is the subgroup of Multiplicative Abelian Group
            isomorphic to Z x Z x C30 x C64 x C729 generated by [a*b,
            c^6, d]
        
        ::
        
            sage: G = F.subgroup([a*b,c^6,d],names = list("xyz")); G
            Multiplicative Abelian Group isomorphic to C5 x C64 x Z,
            which is the subgroup of Multiplicative Abelian Group
            isomorphic to Z x Z x C30 x C64 x C729 generated by [a*b,
            c^6, d]
            sage: x,y,z = G.gens()
            sage: x.order()
            +Infinity
            sage: y.order()
            5
            sage: z.order()
            64
            sage: A = AbelianGroup(5,[3, 5, 5, 7, 8], names = "abcde")
            sage: a,b,c,d,e = A.gens()
            sage: A.subgroup([a,b])
            Multiplicative Abelian Group isomorphic to C3 x C5, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
            generated by [a, b]
            sage: A.subgroup([a,b,c,d^2,e])
            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
            generated by [a, b, c, d^2, e]
            sage: A.subgroup([a,b,c,d^2,e^2])
            Multiplicative Abelian Group isomorphic to C3 x C4 x C5 x C5 x C7, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
            generated by [a, b, c, d^2, e^2]
            sage: B = A.subgroup([a^3,b,c,d,e^2]); B
            Multiplicative Abelian Group isomorphic to C4 x C5 x C5 x C7, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
            generated by [b, c, d, e^2]
            sage: B.invariants()
            [4, 5, 5, 7]
            sage: A = AbelianGroup(4,[1009, 2003, 3001, 4001], names = "abcd")
            sage: a,b,c,d = A.gens()
            sage: B = A.subgroup([a^3,b,c,d])
            sage: B.invariants()
            [1009, 2003, 3001, 4001]
            sage: A.order()
            24266473210027
            sage: B.order()
            24266473210027
            sage: A = AbelianGroup(4,[1008, 2003, 3001, 4001], names = "abcd")
            sage: a,b,c,d = A.gens()
            sage: B = A.subgroup([a^3,b,c,d]); B
            Multiplicative Abelian Group isomorphic to C3 x C7 x C16 x
            C2003 x C3001 x C4001, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C1008 x C2003 x
            C3001 x C4001 generated by [a^3, b, c, d]
        
        Infinite groups can also be handled::
        
            sage: G = AbelianGroup([3,4,0], names = "abc")
            sage: a,b,c = G.gens()
            sage: F = G.subgroup([a,b^2,c]); F
            Multiplicative Abelian Group isomorphic to C2 x C3 x Z,
            which is the subgroup of Multiplicative Abelian Group
            isomorphic to C3 x C4 x Z generated by [a, b^2, c]
        
        ::
        
            sage: F.invariants()
            [2, 3, 0]
            sage: F.gens()
            [a, b^2, c]
            sage: F.order()
            +Infinity
        """
        from sage.interfaces.all import gap
        if not isinstance(ambient, AbelianGroup_class):
            raise TypeError, "ambient (=%s) must be an abelian group." % ambient
        if not isinstance(gens, list):
            raise TypeError, "gens (=%s) must be a list" % gens

        self.__ambient_group = ambient
        Hgens = [x for x in gens if x != ambient(1)
                 ]  ## in case someone puts 1 in the list of generators
        self.__gens = Hgens
        m = len(gens)
        ell = len(ambient.gens())
        ambient_invs = ambient.invariants()
        invsf = [x for x in ambient_invs if x > 0]  ## fixes the problem with
        invs0 = [x for x in ambient_invs if x == 0]  ## the infinite parts
        Ggens = list(ambient.variable_names())
        if invs0 != []:
            Gfgens = [
                x for x in ambient.variable_names()
                if ambient_invs[Ggens.index(x)] != 0
            ]
            Ggens0 = [
                x for x in ambient.variable_names()
                if ambient_invs[Ggens.index(x)] == 0
            ]
            ##     ^^ only look at "finite" names
            Gf = AbelianGroup_class(len(invsf), invsf, names=Gfgens)
            s1 = "G:= %s; gens := GeneratorsOfGroup(G)" % Gf._gap_init_()
            gap.eval(s1)
            Hgensf = [
                x for x in Hgens
                if len(set(Ggens0).intersection(set(list(str(x))))) == 0
            ]
            # computes the gens of H which do not occur ^^ in the infinite part of G
            Hgens0 = [x for x in Hgens if not (x in Hgensf)]
            # the "infinite" generators of H
            for i in range(len(Gfgens)):
                cmd = ("%s := gens[" + str(i + 1) + "]") % Gfgens[i]
                gap.eval(cmd)
        if invs0 == []:
            Hgensf = Hgens
            Hgens0 = []  # added for consistency
            G = ambient
            s1 = "G:= %s; gens := GeneratorsOfGroup(G)" % G._gap_init_()
            gap.eval(s1)
            for i in range(len(Ggens)):
                cmd = '%s := gens[%s]' % (Ggens[i], i + 1)
                #print i,"  \n",cmd
                gap.eval(cmd)
        s2 = "gensH:=%s" % Hgensf  #### remove from this the ones <--> 0 invar
        gap.eval(s2)
        s3 = 'H:=Subgroup(G,gensH)'
        gap.eval(s3)
        # a GAP command which returns the "invariants" of the
        # subgroup as an AbelianPcpGroup, RelativeOrdersOfPcp(Pcp(G)),
        # works if G is the subgroup declared as a AbelianPcpGroup
        self.__abinvs = eval(gap.eval("AbelianInvariants(H)"))
        invs = self.__abinvs
        #print s3, invs
        if Hgens0 != []:
            for x in Hgens0:
                invs.append(0)
        #print Hgensf, invs, invs0
        AbelianGroup_class.__init__(self, len(invs), invs, names)
Esempio n. 38
0
def word_problem(words, g, verbose=False):
    r"""
    G and H are abelian, g in G, H is a subgroup of G generated by a
    list (words) of elements of G. If g is in H, return the expression
    for g as a word in the elements of (words).
    
    The 'word problem' for a finite abelian group G boils down to the
    following matrix-vector analog of the Chinese remainder theorem.
    
    Problem: Fix integers `1<n_1\leq n_2\leq ...\leq n_k`
    (indeed, these `n_i` will all be prime powers), fix a
    generating set `g_i=(a_{i1},...,a_{ik})` (with
    `a_{ij}\in \mathrm{Z}/n_j\mathrm{Z}`), for `1\leq i\leq \ell`,
    for the group `G`, and let `d = (d_1,...,d_k)` be
    an element of the direct product
    `\mathrm{Z}/n_1\mathrm{Z} \times ...\times \mathrm{Z}/n_k\mathrm{Z}`. Find, if they
    exist, integers `c_1,...,c_\ell` such that
    `c_1g_1+...+c_\ell g_\ell = d`. In other words, solve
    the equation `cA=d` for `c\in \mathrm{Z}^\ell`, where
    `A` is the matrix whose rows are the `g_i`'s. Of
    course, it suffices to restrict the `c_i`'s to the range
    `0\leq c_i\leq N-1`, where `N` denotes the least
    common multiple of the integers `n_1,...,n_k`.
    
    This function does not solve this directly, as perhaps it should.
    Rather (for both speed and as a model for a similar function valid
    for more general groups), it pushes it over to GAP, which has optimized 
    (non-deterministic) algorithms for the word problem. Essentially, 
    this function is a wrapper for the GAP function 'Factorization'. 
    
    EXAMPLE::
    
        sage: G.<a,b,c> = AbelianGroup(3,[2,3,4]); G
        Multiplicative Abelian Group isomorphic to C2 x C3 x C4
        sage: w = word_problem([a*b,a*c], b*c); w #random 
        [[a*b, 1], [a*c, 1]]  
        sage: prod([x^i for x,i in w]) == b*c
        True
        sage: w = word_problem([a*c,c],a); w #random 
        [[a*c, 1], [c, -1]]   
        sage: prod([x^i for x,i in w]) == a 
        True
        sage: word_problem([a*c,c],a,verbose=True) #random
        a = (a*c)^1*(c)^-1
        [[a*c, 1], [c, -1]]
    
    ::
    
        sage: A.<a,b,c,d,e> = AbelianGroup(5,[4, 5, 5, 7, 8])
        sage: b1 = a^3*b*c*d^2*e^5
        sage: b2 = a^2*b*c^2*d^3*e^3
        sage: b3 = a^7*b^3*c^5*d^4*e^4
        sage: b4 = a^3*b^2*c^2*d^3*e^5
        sage: b5 = a^2*b^4*c^2*d^4*e^5
        sage: w = word_problem([b1,b2,b3,b4,b5],e); w #random
        [[a^3*b*c*d^2*e^5, 1], [a^2*b*c^2*d^3*e^3, 1], [a^3*b^3*d^4*e^4, 3], [a^2*b^4*c^2*d^4*e^5, 1]]
        sage: prod([x^i for x,i in w]) == e 
        True
        sage: word_problem([a,b,c,d,e],e)
        [[e, 1]]
        sage: word_problem([a,b,c,d,e],b)
        [[b, 1]]
    
    .. warning::

       1. Might have unpleasant effect when the word problem
          cannot be solved.
    
       2. Uses permutation groups, so may be slow when group is large.
          The instance method word_problem of the class
          AbelianGroupElement is implemented differently (wrapping
          GAP's 'EpimorphismFromFreeGroup' and
          'PreImagesRepresentative') and may be faster.
       
    """
    from sage.interfaces.all import gap
    G = g.parent()
    invs = G.invariants()
    gap.eval("l:=One(Rationals)")
    s1 = 'A:=AbelianGroup(%s)' % invs
    gap.eval(s1)
    s2 = 'phi:=IsomorphismPermGroup(A)'
    gap.eval(s2)
    s3 = "gens := GeneratorsOfGroup(A)"
    gap.eval(s3)
    L = g.list()
    gap.eval("L1:=" + str(L))
    s4 = "L2:=List([l..%s], i->gens[i]^L1[i]);" % len(L)
    gap.eval(s4)
    gap.eval("g:=Product(L2); gensH:=[]")
    for w in words:
        L = w.list()
        gap.eval("L1:=" + str(L))
        s4 = "L2:=List([1..%s], i->gens[i]^L1[i]);" % len(L)
        gap.eval(s4)
        gap.eval("w:=Product(L2)")
        gap.eval("gensH:=Concatenation(gensH,[w])")
    s5 = 'H:=Group(gensH)'
    gap.eval(s5)
    gap.eval("x:=Factorization(H,g)")
    l3 = eval(gap.eval("L3:=ExtRepOfObj(x)"))
    nn = gap.eval("n:=Int(Length(L3)/2)")
    LL = eval(gap.eval("L4:=List([l..n],i->L3[2*i])"))
    if verbose:
        #print gap.eval("x"), l3, nn, LL
        v = '*'.join([
            '(%s)^%s' % (words[l3[2 * i] - 1], LL[i]) for i in range(len(LL))
        ])
        print '%s = %s' % (g, v)
    return [[words[l3[2 * i] - 1], LL[i]] for i in range(len(LL))]
Esempio n. 39
0
def bounds_on_minimum_distance_in_guava(n, k, F):
    r"""
    Computes a lower and upper bound on the greatest minimum distance of a
    `[n,k]` linear code over the field ``F``.

    This function requires the optional GAP package GUAVA.

    The function returns a GAP record with the two bounds and an explanation for
    each bound. The function Display can be used to show the explanations.

    The values for the lower and upper bound are obtained from a table
    constructed by Cen Tjhai for GUAVA, derived from the table of
    Brouwer. See http://www.codetables.de/ for the most recent data.
    These tables contain lower and upper bounds for `q=2` (when ``n <= 257``),
    `q=3` (when ``n <= 243``), `q=4` (``n <= 256``). (Current as of
    11 May 2006.) For codes over other fields and for larger word lengths,
    trivial bounds are used.

    INPUT:

    - ``n`` -- the length of the code to look up

    - ``k`` -- the dimension of the code to look up

    - ``F`` -- the base field of the code to look up

    OUTPUT:

    - A GAP record object. See below for an example.

    EXAMPLES::

        sage: gap_rec = codes.databases.bounds_on_minimum_distance_in_guava(10,5,GF(2))  # optional - gap_packages (Guava package)
        sage: print(gap_rec)                                                             # optional - gap_packages (Guava package)
        rec(
          construction :=
           [ <Operation "ShortenedCode">,
              [
                  [ <Operation "UUVCode">,
                      [
                          [ <Operation "DualCode">,
                              [ [ <Operation "RepetitionCode">, [ 8, 2 ] ] ] ],
                          [ <Operation "UUVCode">,
                              [
                                  [ <Operation "DualCode">,
                                      [ [ <Operation "RepetitionCode">, [ 4, 2 ] ] ] ]
                                    , [ <Operation "RepetitionCode">, [ 4, 2 ] ] ] ]
                         ] ], [ 1, 2, 3, 4, 5, 6 ] ] ],
          k := 5,
          lowerBound := 4,
          lowerBoundExplanation := ...
          n := 10,
          q := 2,
          references := rec(
               ),
          upperBound := 4,
          upperBoundExplanation := ... )
    """
    GapPackage("guava", spkg="gap_packages").require()
    gap.load_package("guava")
    q = F.order()
    gap.eval("data := BoundsMinimumDistance(%s,%s,GF(%s))" % (n, k, q))
    Ldata = gap.eval("Display(data)")
    return Ldata
Esempio n. 40
0
    def subgroups(self, check=False):
        r"""
        Compute all the subgroups of this abelian group (which must be finite).
        
        TODO: This is *many orders of magnitude* slower than Magma.

        INPUT:

        - check: if True, performs the same computation in GAP and checks that
          the number of subgroups generated is the same. (I don't know how to
          convert GAP's output back into Sage, so we don't actually compare the
          subgroups).

        ALGORITHM:

            If the group is cyclic, the problem is easy. Otherwise, write it as
            a direct product A x B, where B is cyclic. Compute the subgroups of
            A (by recursion).

            Now, for every subgroup C of A x B, let G be its *projection onto*
            A and H its *intersection with* B. Then there is a well-defined
            homomorphism f: G -> B/H that sends a in G to the class mod H of b,
            where (a,b) is any element of C lifting a; and every subgroup C
            arises from a unique triple (G, H, f). 

        EXAMPLES::

            sage: AbelianGroup([2,3]).subgroups()
            [Multiplicative Abelian Group isomorphic to C2 x C3, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C2 x C3
            generated by [f0*f1^2],
             Multiplicative Abelian Group isomorphic to C2, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C2 x C3
            generated by [f0],
             Multiplicative Abelian Group isomorphic to C3, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C2 x C3
            generated by [f1],
             Trivial Abelian Group, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C2 x C3
            generated by []]

            sage: len(AbelianGroup([2,4,8]).subgroups())
            81

        """
        if not self.is_finite(): raise ValueError, "Group must be finite"
        from sage.misc.misc import verbose

        v = self.invariants()

        if len(v) <= 1:
            if v == [] or v[0] == 1:
                return [self]
            else:
                return [
                    self.subgroup([self.gen(0)**i])
                    for i in divisors(v[0])[:-1]
                ] + [self.subgroup([])]

        A = AbelianGroup(v[:-1])
        x = v[-1]

        Wsubs = A.subgroups()

        subgps = []
        for G in Wsubs:
            verbose("G = subgp generated by %s" % G.gens())
            verbose("invariants are:",
                    [t.order()
                     for t in G.gens()])  # G.invariants() doesn't work
            for H in divisors(x):
                # H = the subgroup of *index* H.
                its = [
                    xrange(0, H, H / gcd(H,
                                         G.gen(i).order()))
                    for i in xrange(len(G.gens()))
                ]
                for f in cartesian_product_iterator(its):
                    verbose("using hom from G to C_%s sending gens to %s" %
                            (H, f))
                    new_sub = []
                    for a in xrange(len(G.gens())):
                        new_sub.append(G.gen(a).list() + [f[a]])
                    if H != x:
                        new_sub.append([0] * A.ngens() + [H])
                    subgps.append(self.subgroup_reduced(new_sub))

        if check:
            from sage.interfaces.all import gap
            verbose("Running Gap cross-check")
            t = ZZ(
                gap.eval("Size(SubgroupsSolvableGroup(AbelianGroup(%s)))" % v))
            if t != len(subgps):
                raise ArithmeticError, "For %s Gap finds %s subgroups, I found %s" % (
                    v, t, len(subgps))
            verbose("Gap check OK for %s: %s" % (v, t))
        return subgps
Esempio n. 41
0
def codesize_upper_bound(n,d,q,algorithm=None):
    r"""
    Returns an upper bound on the number of codewords in a (possibly non-linear)
    code.

    This function computes the minimum value of the upper bounds of Singleton,
    Hamming, Plotkin, and Elias.

    If algorithm="gap" then this returns the best known upper
    bound `A(n,d)=A_q(n,d)` for the size of a code of length n,
    minimum distance d over a field of size q. The function first
    checks for trivial cases (like d=1 or n=d), and if the value
    is in the built-in table. Then it calculates the minimum value
    of the upper bound using the algorithms of Singleton, Hamming,
    Johnson, Plotkin and Elias. If the code is binary,
    `A(n, 2\ell-1) = A(n+1,2\ell)`, so the function
    takes the minimum of the values obtained from all algorithms for the
    parameters `(n, 2\ell-1)` and `(n+1, 2\ell)`. This
    wraps GUAVA's (i.e. GAP's package Guava) UpperBound( n, d, q ).

    If algorithm="LP" then this returns the Delsarte (a.k.a. Linear
    Programming) upper bound.

    EXAMPLES::

        sage: codes.bounds.codesize_upper_bound(10,3,2)
        93
        sage: codes.bounds.codesize_upper_bound(24,8,2,algorithm="LP")
        4096
        sage: codes.bounds.codesize_upper_bound(10,3,2,algorithm="gap")  # optional - gap_packages (Guava package)
        85
        sage: codes.bounds.codesize_upper_bound(11,3,4,algorithm=None)
        123361
        sage: codes.bounds.codesize_upper_bound(11,3,4,algorithm="gap")  # optional - gap_packages (Guava package)
        123361
        sage: codes.bounds.codesize_upper_bound(11,3,4,algorithm="LP")
        109226

    TESTS:

    Make sure :trac:`22961` is fixed::

        sage: codes.bounds.codesize_upper_bound(19,10,2)
        20
        sage: codes.bounds.codesize_upper_bound(19,10,2,algorithm="gap") # optional - gap_packages (Guava package)
        20

    Meaningless parameters are rejected::

        sage: codes.bounds.codesize_upper_bound(10, -20, 6)
        Traceback (most recent call last):
        ...
        ValueError: The length or minimum distance does not make sense
    """
    _check_n_q_d(n, q, d, field_based=False)
    if algorithm=="gap":
        gap.load_package('guava')
        return int(gap.eval("UpperBound(%s,%s,%s)"%( n, d, q )))
    if algorithm=="LP":
        return int(delsarte_bound_hamming_space(n,d,q))
    else:
        eub = elias_upper_bound(n,q,d)
        hub = hamming_upper_bound(n,q,d)
        pub = plotkin_upper_bound(n,q,d)
        sub = singleton_upper_bound(n,q,d)
        return min([eub,hub,pub,sub])
Esempio n. 42
0
 def __init__(self, ambient, gens, names="f"):
     """
     EXAMPLES::
     
         sage: F = AbelianGroup(5,[30,64,729],names = list("abcde"))
         sage: a,b,c,d,e = F.gens()
         sage: F.subgroup([a^3,b])
         Multiplicative Abelian Group isomorphic to Z x Z, which is the subgroup of
         Multiplicative Abelian Group isomorphic to Z x Z x C30 x C64 x C729
         generated by [a^3, b]            
     
     ::
     
         sage: F.subgroup([c])
         Multiplicative Abelian Group isomorphic to C2 x C3 x C5, which is the subgroup of
         Multiplicative Abelian Group isomorphic to Z x Z x C30 x C64 x C729
         generated by [c]
     
     ::
     
         sage: F.subgroup([a,c])
         Multiplicative Abelian Group isomorphic to C2 x C3 x C5 x
         Z, which is the subgroup of Multiplicative Abelian Group
         isomorphic to Z x Z x C30 x C64 x C729 generated by [a, c]
     
     ::
     
         sage: F.subgroup([a,b*c])
         Multiplicative Abelian Group isomorphic to Z x Z, which is
         the subgroup of Multiplicative Abelian Group isomorphic to
         Z x Z x C30 x C64 x C729 generated by [a, b*c]
     
     ::
     
         sage: F.subgroup([b*c,d])
         Multiplicative Abelian Group isomorphic to C64 x Z, which
         is the subgroup of Multiplicative Abelian Group isomorphic
         to Z x Z x C30 x C64 x C729 generated by [b*c, d]
     
     ::
     
         sage: F.subgroup([a*b,c^6,d],names = list("xyz"))
         Multiplicative Abelian Group isomorphic to C5 x C64 x Z,
         which is the subgroup of Multiplicative Abelian Group
         isomorphic to Z x Z x C30 x C64 x C729 generated by [a*b,
         c^6, d]
     
     ::
     
         sage: H.<x,y,z> = F.subgroup([a*b, c^6, d]); H
         Multiplicative Abelian Group isomorphic to C5 x C64 x Z,
         which is the subgroup of Multiplicative Abelian Group
         isomorphic to Z x Z x C30 x C64 x C729 generated by [a*b,
         c^6, d]
     
     ::
     
         sage: G = F.subgroup([a*b,c^6,d],names = list("xyz")); G
         Multiplicative Abelian Group isomorphic to C5 x C64 x Z,
         which is the subgroup of Multiplicative Abelian Group
         isomorphic to Z x Z x C30 x C64 x C729 generated by [a*b,
         c^6, d]
         sage: x,y,z = G.gens()
         sage: x.order()
         +Infinity
         sage: y.order()
         5
         sage: z.order()
         64
         sage: A = AbelianGroup(5,[3, 5, 5, 7, 8], names = "abcde")
         sage: a,b,c,d,e = A.gens()
         sage: A.subgroup([a,b])
         Multiplicative Abelian Group isomorphic to C3 x C5, which is the subgroup of
         Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
         generated by [a, b]
         sage: A.subgroup([a,b,c,d^2,e])
         Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8, which is the subgroup of
         Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
         generated by [a, b, c, d^2, e]
         sage: A.subgroup([a,b,c,d^2,e^2])
         Multiplicative Abelian Group isomorphic to C3 x C4 x C5 x C5 x C7, which is the subgroup of
         Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
         generated by [a, b, c, d^2, e^2]
         sage: B = A.subgroup([a^3,b,c,d,e^2]); B
         Multiplicative Abelian Group isomorphic to C4 x C5 x C5 x C7, which is the subgroup of
         Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
         generated by [b, c, d, e^2]
         sage: B.invariants()
         [4, 5, 5, 7]
         sage: A = AbelianGroup(4,[1009, 2003, 3001, 4001], names = "abcd")
         sage: a,b,c,d = A.gens()
         sage: B = A.subgroup([a^3,b,c,d])
         sage: B.invariants()
         [1009, 2003, 3001, 4001]
         sage: A.order()
         24266473210027
         sage: B.order()
         24266473210027
         sage: A = AbelianGroup(4,[1008, 2003, 3001, 4001], names = "abcd")
         sage: a,b,c,d = A.gens()
         sage: B = A.subgroup([a^3,b,c,d]); B
         Multiplicative Abelian Group isomorphic to C3 x C7 x C16 x
         C2003 x C3001 x C4001, which is the subgroup of
         Multiplicative Abelian Group isomorphic to C1008 x C2003 x
         C3001 x C4001 generated by [a^3, b, c, d]
     
     Infinite groups can also be handled::
     
         sage: G = AbelianGroup([3,4,0], names = "abc")
         sage: a,b,c = G.gens()
         sage: F = G.subgroup([a,b^2,c]); F
         Multiplicative Abelian Group isomorphic to C2 x C3 x Z,
         which is the subgroup of Multiplicative Abelian Group
         isomorphic to C3 x C4 x Z generated by [a, b^2, c]
     
     ::
     
         sage: F.invariants()
         [2, 3, 0]
         sage: F.gens()
         [a, b^2, c]
         sage: F.order()
         +Infinity
     """
     from sage.interfaces.all import gap
     if not isinstance(ambient, AbelianGroup_class):
         raise TypeError, "ambient (=%s) must be an abelian group."%ambient
     if not isinstance(gens, list):
         raise TypeError, "gens (=%s) must be a list"%gens
         
     self.__ambient_group = ambient
     Hgens = [x for x in gens if x != ambient(1)]  ## in case someone puts 1 in the list of generators
     self.__gens = Hgens
     m = len(gens)
     ell = len(ambient.gens())
     ambient_invs = ambient.invariants()
     invsf = [x for x in ambient_invs if x > 0]    ## fixes the problem with 
     invs0 = [x for x in ambient_invs if x == 0]   ## the infinite parts
     Ggens = list(ambient.variable_names())
     if invs0!=[]:
         Gfgens = [x for x in ambient.variable_names() if
                     ambient_invs[Ggens.index(x)] != 0]
         Ggens0 = [x for x in ambient.variable_names() if
                     ambient_invs[Ggens.index(x)] == 0]
         ##     ^^ only look at "finite" names 
         Gf = AbelianGroup_class(len(invsf), invsf, names = Gfgens)
         s1 = "G:= %s; gens := GeneratorsOfGroup(G)"%Gf._gap_init_()
         gap.eval(s1)
         Hgensf = [x for x in Hgens if len(set(Ggens0).intersection(set(list(str(x)))))==0]
         # computes the gens of H which do not occur ^^ in the infinite part of G
         Hgens0 = [x for x in Hgens if not(x in Hgensf)]
         # the "infinite" generators of H
         for i in range(len(Gfgens)):
            cmd = ("%s := gens["+str(i+1)+"]")%Gfgens[i]
            gap.eval(cmd)
     if invs0==[]:
        Hgensf = Hgens
        Hgens0 = []  # added for consistency
        G = ambient
        s1 = "G:= %s; gens := GeneratorsOfGroup(G)"%G._gap_init_()
        gap.eval(s1)
        for i in range(len(Ggens)):
            cmd = '%s := gens[%s]'%(Ggens[i], i+1)
            #print i,"  \n",cmd
            gap.eval(cmd)
     s2 = "gensH:=%s"%Hgensf #### remove from this the ones <--> 0 invar
     gap.eval(s2)
     s3 = 'H:=Subgroup(G,gensH)'
     gap.eval(s3)
     # a GAP command which returns the "invariants" of the
     # subgroup as an AbelianPcpGroup, RelativeOrdersOfPcp(Pcp(G)),
     # works if G is the subgroup declared as a AbelianPcpGroup
     self.__abinvs = eval(gap.eval("AbelianInvariants(H)"))
     invs = self.__abinvs
     #print s3, invs
     if Hgens0 != []:
         for x in Hgens0:
            invs.append(0)
     #print Hgensf, invs, invs0
     AbelianGroup_class.__init__(self, len(invs), invs, names)
Esempio n. 43
0
def word_problem(words, g, verbose = False):
    r"""
    G and H are abelian, g in G, H is a subgroup of G generated by a
    list (words) of elements of G. If g is in H, return the expression
    for g as a word in the elements of (words).
    
    The 'word problem' for a finite abelian group G boils down to the
    following matrix-vector analog of the Chinese remainder theorem.
    
    Problem: Fix integers `1<n_1\leq n_2\leq ...\leq n_k`
    (indeed, these `n_i` will all be prime powers), fix a
    generating set `g_i=(a_{i1},...,a_{ik})` (with
    `a_{ij}\in \mathrm{Z}/n_j\mathrm{Z}`), for `1\leq i\leq \ell`,
    for the group `G`, and let `d = (d_1,...,d_k)` be
    an element of the direct product
    `\mathrm{Z}/n_1\mathrm{Z} \times ...\times \mathrm{Z}/n_k\mathrm{Z}`. Find, if they
    exist, integers `c_1,...,c_\ell` such that
    `c_1g_1+...+c_\ell g_\ell = d`. In other words, solve
    the equation `cA=d` for `c\in \mathrm{Z}^\ell`, where
    `A` is the matrix whose rows are the `g_i`'s. Of
    course, it suffices to restrict the `c_i`'s to the range
    `0\leq c_i\leq N-1`, where `N` denotes the least
    common multiple of the integers `n_1,...,n_k`.
    
    This function does not solve this directly, as perhaps it should.
    Rather (for both speed and as a model for a similar function valid
    for more general groups), it pushes it over to GAP, which has optimized 
    (non-deterministic) algorithms for the word problem. Essentially, 
    this function is a wrapper for the GAP function 'Factorization'. 
    
    EXAMPLE::
    
        sage: G.<a,b,c> = AbelianGroup(3,[2,3,4]); G
        Multiplicative Abelian Group isomorphic to C2 x C3 x C4
        sage: w = word_problem([a*b,a*c], b*c); w #random 
        [[a*b, 1], [a*c, 1]]  
        sage: prod([x^i for x,i in w]) == b*c
        True
        sage: w = word_problem([a*c,c],a); w #random 
        [[a*c, 1], [c, -1]]   
        sage: prod([x^i for x,i in w]) == a 
        True
        sage: word_problem([a*c,c],a,verbose=True) #random
        a = (a*c)^1*(c)^-1
        [[a*c, 1], [c, -1]]
    
    ::
    
        sage: A.<a,b,c,d,e> = AbelianGroup(5,[4, 5, 5, 7, 8])
        sage: b1 = a^3*b*c*d^2*e^5
        sage: b2 = a^2*b*c^2*d^3*e^3
        sage: b3 = a^7*b^3*c^5*d^4*e^4
        sage: b4 = a^3*b^2*c^2*d^3*e^5
        sage: b5 = a^2*b^4*c^2*d^4*e^5
        sage: w = word_problem([b1,b2,b3,b4,b5],e); w #random
        [[a^3*b*c*d^2*e^5, 1], [a^2*b*c^2*d^3*e^3, 1], [a^3*b^3*d^4*e^4, 3], [a^2*b^4*c^2*d^4*e^5, 1]]
        sage: prod([x^i for x,i in w]) == e 
        True
        sage: word_problem([a,b,c,d,e],e)
        [[e, 1]]
        sage: word_problem([a,b,c,d,e],b)
        [[b, 1]]
    
    .. warning::

       1. Might have unpleasant effect when the word problem
          cannot be solved.
    
       2. Uses permutation groups, so may be slow when group is large.
          The instance method word_problem of the class
          AbelianGroupElement is implemented differently (wrapping
          GAP's 'EpimorphismFromFreeGroup' and
          'PreImagesRepresentative') and may be faster.
       
    """
    from sage.interfaces.all import gap
    G = g.parent()
    invs = G.invariants()
    gap.eval("l:=One(Rationals)")
    s1 = 'A:=AbelianGroup(%s)'%invs
    gap.eval(s1)
    s2 = 'phi:=IsomorphismPermGroup(A)'
    gap.eval(s2)
    s3 = "gens := GeneratorsOfGroup(A)"
    gap.eval(s3)
    L = g.list()
    gap.eval("L1:="+str(L))
    s4 = "L2:=List([l..%s], i->gens[i]^L1[i]);"%len(L) 
    gap.eval(s4)
    gap.eval("g:=Product(L2); gensH:=[]")
    for w in words:
         L = w.list()
         gap.eval("L1:="+str(L))
         s4 = "L2:=List([1..%s], i->gens[i]^L1[i]);"%len(L) 
         gap.eval(s4)
         gap.eval("w:=Product(L2)")
         gap.eval("gensH:=Concatenation(gensH,[w])")
    s5 = 'H:=Group(gensH)'
    gap.eval(s5)
    gap.eval("x:=Factorization(H,g)")
    l3 = eval(gap.eval("L3:=ExtRepOfObj(x)"))
    nn = gap.eval("n:=Int(Length(L3)/2)")
    LL = eval(gap.eval("L4:=List([l..n],i->L3[2*i])"))
    if verbose:
        #print gap.eval("x"), l3, nn, LL
        v = '*'.join(['(%s)^%s'%(words[l3[2*i]-1], LL[i]) for i in range(len(LL))])
        print '%s = %s'%(g, v)
    return [[words[l3[2*i]-1],LL[i]] for i in range(len(LL))]
Esempio n. 44
0
def bounds_on_minimum_distance_in_guava(n, k, F):
    r"""
    Computes a lower and upper bound on the greatest minimum distance of a
    `[n,k]` linear code over the field ``F``.

    This function requires the optional GAP package GUAVA.

    The function returns a GAP record with the two bounds and an explanation for
    each bound. The function Display can be used to show the explanations.

    The values for the lower and upper bound are obtained from a table
    constructed by Cen Tjhai for GUAVA, derived from the table of
    Brouwer. See http://www.codetables.de/ for the most recent data.
    These tables contain lower and upper bounds for `q=2` (when ``n <= 257``),
    `q=3` (when ``n <= 243``), `q=4` (``n <= 256``). (Current as of
    11 May 2006.) For codes over other fields and for larger word lengths,
    trivial bounds are used.

    INPUT:

    - ``n`` -- the length of the code to look up

    - ``k`` -- the dimension of the code to look up

    - ``F`` -- the base field of the code to look up

    OUTPUT:

    - A GAP record object. See below for an example.

    EXAMPLES::

        sage: gap_rec = codes.databases.bounds_on_minimum_distance_in_guava(10,5,GF(2))  # optional - gap_packages (Guava package)
        sage: print(gap_rec)                                                             # optional - gap_packages (Guava package)
        rec(
          construction :=
           [ <Operation "ShortenedCode">,
              [
                  [ <Operation "UUVCode">,
                      [
                          [ <Operation "DualCode">,
                              [ [ <Operation "RepetitionCode">, [ 8, 2 ] ] ] ],
                          [ <Operation "UUVCode">,
                              [
                                  [ <Operation "DualCode">,
                                      [ [ <Operation "RepetitionCode">, [ 4, 2 ] ] ] ]
                                    , [ <Operation "RepetitionCode">, [ 4, 2 ] ] ] ]
                         ] ], [ 1, 2, 3, 4, 5, 6 ] ] ],
          k := 5,
          lowerBound := 4,
          lowerBoundExplanation := ...
          n := 10,
          q := 2,
          references := rec(
               ),
          upperBound := 4,
          upperBoundExplanation := ... )
    """
    from sage.interfaces.all import gap
    gap.load_package("guava")
    q = F.order()
    gap.eval("data := BoundsMinimumDistance(%s,%s,GF(%s))"%(n,k,q))
    Ldata = gap.eval("Display(data)")
    return Ldata
Esempio n. 45
0
    def subgroups(self, check=False):
        r"""
        Compute all the subgroups of this abelian group (which must be finite).
        
        TODO: This is *many orders of magnitude* slower than Magma.

        INPUT:

        - check: if True, performs the same computation in GAP and checks that
          the number of subgroups generated is the same. (I don't know how to
          convert GAP's output back into Sage, so we don't actually compare the
          subgroups).

        ALGORITHM:

            If the group is cyclic, the problem is easy. Otherwise, write it as
            a direct product A x B, where B is cyclic. Compute the subgroups of
            A (by recursion).

            Now, for every subgroup C of A x B, let G be its *projection onto*
            A and H its *intersection with* B. Then there is a well-defined
            homomorphism f: G -> B/H that sends a in G to the class mod H of b,
            where (a,b) is any element of C lifting a; and every subgroup C
            arises from a unique triple (G, H, f). 

        EXAMPLES::

            sage: AbelianGroup([2,3]).subgroups()
            [Multiplicative Abelian Group isomorphic to C2 x C3, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C2 x C3
            generated by [f0*f1^2],
             Multiplicative Abelian Group isomorphic to C2, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C2 x C3
            generated by [f0],
             Multiplicative Abelian Group isomorphic to C3, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C2 x C3
            generated by [f1],
             Trivial Abelian Group, which is the subgroup of
            Multiplicative Abelian Group isomorphic to C2 x C3
            generated by []]

            sage: len(AbelianGroup([2,4,8]).subgroups())
            81

        """
        if not self.is_finite(): raise ValueError, "Group must be finite"
        from sage.misc.misc import verbose

        v = self.invariants()
        
        
        if len(v) <= 1:
            if v == [] or v[0] == 1:
                return [self]
            else:
                return [ self.subgroup([self.gen(0)**i]) for i in divisors(v[0])[:-1]] + [self.subgroup([])]

        A = AbelianGroup(v[:-1])
        x = v[-1]

        Wsubs = A.subgroups()

        subgps = []
        for G in Wsubs:
            verbose("G = subgp generated by %s" % G.gens())
            verbose("invariants are:", [t.order() for t in G.gens()]) # G.invariants() doesn't work
            for H in divisors(x):
                # H = the subgroup of *index* H.
                its = [xrange(0, H, H/gcd(H, G.gen(i).order())) for i in xrange(len(G.gens()))] 
                for f in cartesian_product_iterator(its):
                    verbose("using hom from G to C_%s sending gens to %s" % (H,f))
                    new_sub = []
                    for a in xrange(len(G.gens())):
                        new_sub.append(G.gen(a).list() + [f[a]])
                    if H != x:
                        new_sub.append([0]*A.ngens() + [H])
                    subgps.append(self.subgroup_reduced(new_sub))
        
        if check:
            from sage.interfaces.all import gap
            verbose("Running Gap cross-check")
            t = ZZ(gap.eval("Size(SubgroupsSolvableGroup(AbelianGroup(%s)))" % v))
            if t != len(subgps):
                raise ArithmeticError, "For %s Gap finds %s subgroups, I found %s" % (v, t, len(subgps))
            verbose("Gap check OK for %s: %s" % (v, t))
        return subgps
Esempio n. 46
0
 def as_permutation(self):
     r"""
     Return the element of the permutation group G (isomorphic to the
     abelian group A) associated to a in A.
     
     EXAMPLES::
     
         sage: G = AbelianGroup(3,[2,3,4],names="abc"); G
         Multiplicative Abelian Group isomorphic to C2 x C3 x C4
         sage: a,b,c=G.gens()
         sage: Gp = G.permutation_group(); Gp
         Permutation Group with generators [(1,3,2,4)(5,7,6,8)(9,11,10,12)(13,15,14,16)(17,19,18,20)(21,23,22,24), (1,5,9)(2,6,10)(3,7,11)(4,8,12)(13,17,21)(14,18,22)(15,19,23)(16,20,24), (1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)]
         sage: a.as_permutation()
         (1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)
         sage: ap = a.as_permutation(); ap
         (1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)
         sage: ap in Gp
         True
     """
     from sage.groups.perm_gps.permgroup import PermutationGroup
     from sage.interfaces.all import gap
     G = self.parent()
     invs = G.invariants()
     s1 = 'A:=AbelianGroup(%s)' % invs
     gap.eval(s1)
     s2 = 'phi:=IsomorphismPermGroup(A)'
     gap.eval(s2)
     s3 = "gens := GeneratorsOfGroup(A)"
     gap.eval(s3)
     L = self.list()
     gap.eval("L1:=" + str(L))
     s4 = "L2:=List([1..%s], i->gens[i]^L1[i]);" % len(L)
     gap.eval(s4)
     pg = gap.eval("Image(phi,Product(L2))")
     Gp = G.permutation_group()
     gp = Gp(pg)
     return gp
Esempio n. 47
0
 def as_permutation(self):
     r"""
     Return the element of the permutation group G (isomorphic to the
     abelian group A) associated to a in A.
     
     EXAMPLES::
     
         sage: G = AbelianGroup(3,[2,3,4],names="abc"); G
         Multiplicative Abelian Group isomorphic to C2 x C3 x C4
         sage: a,b,c=G.gens()
         sage: Gp = G.permutation_group(); Gp
         Permutation Group with generators [(1,3,2,4)(5,7,6,8)(9,11,10,12)(13,15,14,16)(17,19,18,20)(21,23,22,24), (1,5,9)(2,6,10)(3,7,11)(4,8,12)(13,17,21)(14,18,22)(15,19,23)(16,20,24), (1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)]
         sage: a.as_permutation()
         (1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)
         sage: ap = a.as_permutation(); ap
         (1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)
         sage: ap in Gp
         True
     """
     from sage.groups.perm_gps.permgroup import PermutationGroup
     from sage.interfaces.all import gap
     G = self.parent()
     invs = G.invariants()
     s1 = 'A:=AbelianGroup(%s)'%invs
     gap.eval(s1)
     s2 = 'phi:=IsomorphismPermGroup(A)'
     gap.eval(s2)
     s3 = "gens := GeneratorsOfGroup(A)"
     gap.eval(s3)
     L = self.list()
     gap.eval("L1:="+str(L))
     s4 = "L2:=List([1..%s], i->gens[i]^L1[i]);"%len(L)
     gap.eval(s4)
     pg = gap.eval("Image(phi,Product(L2))")
     Gp = G.permutation_group()
     gp = Gp(pg)
     return gp
Esempio n. 48
0
    def word_problem(self, words, display=True):
        """
        This is a rather hackish method and is included for completeness.

        The word problem for an instance of DualAbelianGroup as it can
        for an AbelianGroup. The reason why is that word problem
        for an instance of AbelianGroup simply calls GAP (which
        has abelian groups implemented) and invokes "EpimorphismFromFreeGroup"
        and "PreImagesRepresentative". GAP does not have duals of
        abelian groups implemented. So, by using the same name
        for the generators, the method below converts the problem for
        the dual group to the corresponding problem on the group
        itself and uses GAP to solve that.

        EXAMPLES::

            sage: G = AbelianGroup(5,[3, 5, 5, 7, 8],names="abcde")
            sage: Gd = G.dual_group(names="abcde")
            sage: a,b,c,d,e = Gd.gens()
            sage: u = a^3*b*c*d^2*e^5
            sage: v = a^2*b*c^2*d^3*e^3
            sage: w = a^7*b^3*c^5*d^4*e^4
            sage: x = a^3*b^2*c^2*d^3*e^5
            sage: y = a^2*b^4*c^2*d^4*e^5
            sage: e.word_problem([u,v,w,x,y],display=False)
            [[b^2*c^2*d^3*e^5, 245]]

        The command e.word_problem([u,v,w,x,y],display=True) returns
        the same list but also prints $e = (b^2*c^2*d^3*e^5)^245$.
        """
        ## First convert the problem to one using AbelianGroups
        import copy
        from sage.groups.abelian_gps.abelian_group import AbelianGroup
        from sage.interfaces.all import gap
        M = self.parent()
        G = M.group()
        gens = M.variable_names()
        g = prod([G.gen(i)**(self.list()[i]) for i in range(G.ngens())])
        gap.eval("l:=One(Rationals)"
                 )  ## trick needed for LL line below to keep Sage from parsing
        s1 = "gens := GeneratorsOfGroup(%s)" % G._gap_init_()
        gap.eval(s1)
        for i in range(len(gens)):
            cmd = ("%s := gens[" + str(i + 1) + "]") % gens[i]
            gap.eval(cmd)
        s2 = "g0:=%s; gensH:=%s" % (str(g), words)
        gap.eval(s2)
        s3 = 'G:=Group(gens); H:=Group(gensH)'
        gap.eval(s3)
        phi = gap.eval("hom:=EpimorphismFromFreeGroup(H)")
        l1 = gap.eval("ans:=PreImagesRepresentative(hom,g0)")
        l2 = copy.copy(l1)
        l4 = []
        l3 = l1.split("*")
        for i in range(1, len(words) + 1):
            l2 = l2.replace("x" + str(i), "(" + str(words[i - 1]) + ")")
        l3 = eval(gap.eval("L3:=ExtRepOfObj(ans)"))
        nn = eval(gap.eval("n:=Int(Length(L3)/2)"))
        LL1 = eval(
            gap.eval("L4:=List([l..n],i->L3[2*i])"))  ## note the l not 1
        LL2 = eval(
            gap.eval("L5:=List([l..n],i->L3[2*i-1])"))  ## note the l not 1
        if display:
            s = str(g) + " = " + add_strings([
                "(" + str(words[LL2[i] - 1]) + ")^" + str(LL1[i]) + "*"
                for i in range(nn)
            ])
            m = len(s)
            print("      ", s[:m - 1], "\n")
        return [[words[LL2[i] - 1], LL1[i]] for i in range(nn)]
Esempio n. 49
0
    def word_problem(self, words, display=True):
        """
        This is a rather hackish method and is included for completeness.

        The word problem for an instance of DualAbelianGroup as it can
        for an AbelianGroup. The reason why is that word problem
        for an instance of AbelianGroup simply calls GAP (which
        has abelian groups implemented) and invokes "EpimorphismFromFreeGroup"
        and "PreImagesRepresentative". GAP does not have duals of
        abelian groups implemented. So, by using the same name
        for the generators, the method below converts the problem for
        the dual group to the corresponding problem on the group
        itself and uses GAP to solve that.

        EXAMPLES::

            sage: G = AbelianGroup(5,[3, 5, 5, 7, 8],names="abcde")
            sage: Gd = G.dual_group(names="abcde")
            sage: a,b,c,d,e = Gd.gens()
            sage: u = a^3*b*c*d^2*e^5
            sage: v = a^2*b*c^2*d^3*e^3
            sage: w = a^7*b^3*c^5*d^4*e^4
            sage: x = a^3*b^2*c^2*d^3*e^5
            sage: y = a^2*b^4*c^2*d^4*e^5
            sage: e.word_problem([u,v,w,x,y],display=False)
            [[b^2*c^2*d^3*e^5, 245]]

        The command e.word_problem([u,v,w,x,y],display=True) returns
        the same list but also prints $e = (b^2*c^2*d^3*e^5)^245$.
        """
        ## First convert the problem to one using AbelianGroups
        import copy
        from sage.groups.abelian_gps.abelian_group import AbelianGroup
        from sage.interfaces.all import gap
        M = self.parent()
        G = M.group()
        gens = M.variable_names()
        g = prod([G.gen(i)**(self.list()[i]) for i in range(G.ngens())])
        gap.eval("l:=One(Rationals)")            ## trick needed for LL line below to keep Sage from parsing
        s1 = "gens := GeneratorsOfGroup(%s)"%G._gap_init_()
        gap.eval(s1)
        for i in range(len(gens)):
           cmd = ("%s := gens["+str(i+1)+"]")%gens[i]
           gap.eval(cmd)
        s2 = "g0:=%s; gensH:=%s"%(str(g),words)
        gap.eval(s2)
        s3 = 'G:=Group(gens); H:=Group(gensH)'
        gap.eval(s3)
        phi = gap.eval("hom:=EpimorphismFromFreeGroup(H)")
        l1 = gap.eval("ans:=PreImagesRepresentative(hom,g0)")
        l2 = copy.copy(l1)
        l4 = []
        l3 = l1.split("*")
        for i in range(1,len(words)+1):
            l2 = l2.replace("x"+str(i),"("+str(words[i-1])+")")
        l3 = eval(gap.eval("L3:=ExtRepOfObj(ans)"))
        nn = eval(gap.eval("n:=Int(Length(L3)/2)"))
        LL1 = eval(gap.eval("L4:=List([l..n],i->L3[2*i])"))         ## note the l not 1
        LL2 = eval(gap.eval("L5:=List([l..n],i->L3[2*i-1])"))       ## note the l not 1
        if display:
            s = str(g)+" = "+add_strings(["("+str(words[LL2[i]-1])+")^"+str(LL1[i])+"*" for i in range(nn)])
            m = len(s)
            print "      ",s[:m-1],"\n"
        return [[words[LL2[i]-1],LL1[i]] for i in range(nn)]
Esempio n. 50
0
    def as_permutation(self):
        r"""
        Return the element of the permutation group G (isomorphic to the
        abelian group A) associated to a in A.

        EXAMPLES::

            sage: G = AbelianGroup(3,[2,3,4],names="abc"); G
            Multiplicative Abelian group isomorphic to C2 x C3 x C4
            sage: a,b,c=G.gens()
            sage: Gp = G.permutation_group(); Gp
            Permutation Group with generators [(6,7,8,9), (3,4,5), (1,2)]
            sage: a.as_permutation()
            (1,2)
            sage: ap = a.as_permutation(); ap
            (1,2)
            sage: ap in Gp
            True
        """
        from sage.groups.perm_gps.permgroup import PermutationGroup
        from sage.interfaces.all import gap
        G = self.parent()
        invs = list(G.gens_orders())
        s1 = 'A:=AbelianGroup(%s)' % invs
        gap.eval(s1)
        s2 = 'phi:=IsomorphismPermGroup(A)'
        gap.eval(s2)
        s3 = "gens := GeneratorsOfGroup(A)"
        gap.eval(s3)
        L = self.list()
        gap.eval("L1:=" + str(L))
        s4 = "L2:=List([1..%s], i->gens[i]^L1[i]);" % len(L)
        gap.eval(s4)
        pg = gap.eval("Image(phi,Product(L2))")
        Gp = G.permutation_group()
        gp = Gp(pg)
        return gp