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))
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))
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))
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))
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))
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))
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))
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))
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))
def _element_constructor_(self, x): r""" Coerce ``x`` into the finite field. INPUT: - ``x`` -- object OUTPUT: If possible, makes a finite field element from ``x``. EXAMPLES:: sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari sage: k = FiniteField_ext_pari(3^4, 'a') sage: b = k(5) # indirect doctest sage: b.parent() Finite Field in a of size 3^4 sage: a = k.gen() sage: k(a + 2) a + 2 Univariate polynomials coerce into finite fields by evaluating the polynomial at the field's generator:: sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari sage: R.<x> = QQ[] sage: k, a = FiniteField_ext_pari(5^2, 'a').objgen() sage: k(R(2/3)) 4 sage: k(x^2) a + 3 sage: R.<x> = GF(5)[] sage: k(x^3-2*x+1) 2*a + 4 sage: x = polygen(QQ) sage: k(x^25) a sage: Q, q = FiniteField_ext_pari(5^7, 'q').objgen() sage: L = GF(5) sage: LL.<xx> = L[] sage: Q(xx^2 + 2*xx + 4) q^2 + 2*q + 4 Multivariate polynomials only coerce if constant:: sage: R = k['x,y,z']; R Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2 sage: k(R(2)) 2 sage: R = QQ['x,y,z'] sage: k(R(1/5)) Traceback (most recent call last): ... TypeError: unable to coerce Gap elements can also be coerced into finite fields:: sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari sage: F = FiniteField_ext_pari(8, 'a') sage: a = F.multiplicative_generator(); a a sage: b = gap(a^3); b Z(2^3)^3 sage: F(b) a + 1 sage: a^3 a + 1 sage: a = GF(13)(gap('0*Z(13)')); a 0 sage: a.parent() Finite Field of size 13 sage: F = GF(16, 'a') sage: F(gap('Z(16)^3')) a^3 sage: F(gap('Z(16)^2')) a^2 You can also call a finite extension field with a string to produce an element of that field, like this:: sage: k = GF(2^8, 'a') sage: k('a^200') a^4 + a^3 + a^2 This is especially useful for fast conversions from Singular etc. to ``FiniteField_ext_pariElements``. AUTHORS: - David Joyner (2005-11) - Martin Albrecht (2006-01-23) - Martin Albrecht (2006-03-06): added coercion from string """ if isinstance(x, element_ext_pari.FiniteField_ext_pariElement): if x.parent() is self: return x elif x.parent() == self: # canonically isomorphic finite fields return element_ext_pari.FiniteField_ext_pariElement(self, x) else: # This is where we *would* do coercion from one finite field to another... raise TypeError, "no coercion defined" elif sage.interfaces.gap.is_GapElement(x): from sage.interfaces.gap import gfq_gap_to_sage try: return gfq_gap_to_sage(x, self) except (ValueError, IndexError, TypeError): raise TypeError, "no coercion defined" if isinstance(x, (int, long, integer.Integer, rational.Rational, pari.pari_gen, list)): return element_ext_pari.FiniteField_ext_pariElement(self, x) elif isinstance(x, multi_polynomial_element.MPolynomial): if x.is_constant(): return self(x.constant_coefficient()) else: raise TypeError, "no coercion defined" elif isinstance(x, polynomial_element.Polynomial): if x.is_constant(): return self(x.constant_coefficient()) else: return x.change_ring(self)(self.gen()) elif isinstance(x, str): x = x.replace(self.variable_name(),'a') x = pari.pari(x) t = x.type() if t == 't_POL': if (x.variable() == 'a' \ and x.polcoeff(0).type()[2] == 'I'): #t_INT and t_INTMOD return self(x) if t[2] == 'I': #t_INT and t_INTMOD return self(x) raise TypeError, "string element does not match this finite field" try: if x.parent() == self.vector_space(): x = pari.pari('+'.join(['%s*a^%s'%(x[i], i) for i in range(self.degree())])) return element_ext_pari.FiniteField_ext_pariElement(self, x) except AttributeError: pass try: return element_ext_pari.FiniteField_ext_pariElement(self, integer.Integer(x)) except TypeError, msg: raise TypeError, "%s\nno coercion defined"%msg
def _element_constructor_(self, x): r""" Coerce ``x`` into the finite field. INPUT: - ``x`` -- object OUTPUT: If possible, makes a finite field element from ``x``. EXAMPLES:: sage: k = FiniteField(3^4, 'a', impl='pari_mod') sage: b = k(5) # indirect doctest sage: b.parent() Finite Field in a of size 3^4 sage: a = k.gen() sage: k(a + 2) a + 2 Univariate polynomials coerce into finite fields by evaluating the polynomial at the field's generator:: sage: R.<x> = QQ[] sage: k.<a> = FiniteField(5^2, impl='pari_mod') sage: k(R(2/3)) 4 sage: k(x^2) a + 3 sage: R.<x> = GF(5)[] sage: k(x^3-2*x+1) 2*a + 4 sage: x = polygen(QQ) sage: k(x^25) a sage: Q.<q> = FiniteField(5^7, impl='pari_mod') sage: L = GF(5) sage: LL.<xx> = L[] sage: Q(xx^2 + 2*xx + 4) q^2 + 2*q + 4 Multivariate polynomials only coerce if constant:: sage: R = k['x,y,z']; R Multivariate Polynomial Ring in x, y, z over Finite Field in a of size 5^2 sage: k(R(2)) 2 sage: R = QQ['x,y,z'] sage: k(R(1/5)) Traceback (most recent call last): ... TypeError: unable to coerce Gap elements can also be coerced into finite fields:: sage: F = FiniteField(8, 'a', impl='pari_mod') sage: a = F.multiplicative_generator(); a a sage: b = gap(a^3); b Z(2^3)^3 sage: F(b) a + 1 sage: a^3 a + 1 sage: a = GF(13)(gap('0*Z(13)')); a 0 sage: a.parent() Finite Field of size 13 sage: F = GF(16, 'a', impl='pari_mod') sage: F(gap('Z(16)^3')) a^3 sage: F(gap('Z(16)^2')) a^2 You can also call a finite extension field with a string to produce an element of that field, like this:: sage: k = GF(2^8, 'a', impl='pari_mod') sage: k('a^200') a^4 + a^3 + a^2 This is especially useful for fast conversions from Singular etc. to ``FiniteField_ext_pariElements``. AUTHORS: - David Joyner (2005-11) - Martin Albrecht (2006-01-23) - Martin Albrecht (2006-03-06): added coercion from string """ if isinstance(x, element_ext_pari.FiniteField_ext_pariElement): if x.parent() is self: return x elif x.parent() == self: # canonically isomorphic finite fields return element_ext_pari.FiniteField_ext_pariElement(self, x) else: raise TypeError("no coercion defined") elif sage.interfaces.gap.is_GapElement(x): from sage.interfaces.gap import gfq_gap_to_sage try: return gfq_gap_to_sage(x, self) except (ValueError, IndexError, TypeError): raise TypeError("no coercion defined") if isinstance(x, (int, long, integer.Integer, rational.Rational, pari.pari_gen, list)): return element_ext_pari.FiniteField_ext_pariElement(self, x) elif isinstance(x, multi_polynomial_element.MPolynomial): if x.is_constant(): return self(x.constant_coefficient()) else: raise TypeError("no coercion defined") elif isinstance(x, polynomial_element.Polynomial): if x.is_constant(): return self(x.constant_coefficient()) else: return x.change_ring(self)(self.gen()) elif isinstance(x, str): x = x.replace(self.variable_name(),'a') x = pari.pari(x) t = x.type() if t == 't_POL': if (x.variable() == 'a' \ and x.polcoeff(0).type()[2] == 'I'): #t_INT and t_INTMOD return self(x) if t[2] == 'I': #t_INT and t_INTMOD return self(x) raise TypeError("string element does not match this finite field") try: if x.parent() == self.vector_space(): x = pari.pari('+'.join(['%s*a^%s'%(x[i], i) for i in range(self.degree())])) return element_ext_pari.FiniteField_ext_pariElement(self, x) except AttributeError: pass try: return element_ext_pari.FiniteField_ext_pariElement(self, integer.Integer(x)) except TypeError as msg: raise TypeError("%s\nno coercion defined"%msg)