Gabidulin Code

This module provides the GabidulinCode, which constructs Gabidulin Codes that are the rank metric equivalent of Reed Solomon codes and are defined as the evaluation codes of degree-restricted skew polynomials.

This module also provides GabidulinPolynomialEvaluationEncoder, an encoder with a skew polynomial message space and GabidulinVectorEvaluationEncoder, an encoder based on the generator matrix. It also provides a decoder GabidulinGaoDecoder which corrects errors using the Gao algorithm in the rank metric.

AUTHOR:

  • Arpit Merchant (2016-08-16)

  • Marketa Slukova (2019-08-19): initial version

class sage.coding.gabidulin_code.GabidulinCode(base_field, length, dimension, sub_field=None, twisting_homomorphism=None, evaluation_points=None)[source]

Bases: AbstractLinearRankMetricCode

A Gabidulin Code.

DEFINITION:

A linear Gabidulin code Gab[n, k] over \(F_{q^m}\) of length \(n\) (at most \(m\)) and dimension \(k\) (at most \(n\)) is the set of all codewords, that are the evaluation of a \(q\)-degree restricted skew polynomial \(f(x)\) belonging to the skew polynomial constructed over the base ring \(F_{q^m}\) and the twisting homomorphism \(\sigma\).

\[\{ \text{Gab[n, k]} = \big\{ (f(g_0) f(g_1) ... f(g_{n-1})) = f(\textbf{g}) : \text{deg}_{q}f(x) < k \big\} \}\]

where the fixed evaluation points \(g_0, g_1,..., g_{n-1}\) are linearly independent over \(F_{q^m}\).

EXAMPLES:

A Gabidulin Code can be constructed in the following way:

sage: Fqm = GF(16)
sage: Fq = GF(4)
sage: C = codes.GabidulinCode(Fqm, 2, 2, Fq)
sage: C
[2, 2, 1] linear Gabidulin code over GF(16)/GF(4)
>>> from sage.all import *
>>> Fqm = GF(Integer(16))
>>> Fq = GF(Integer(4))
>>> C = codes.GabidulinCode(Fqm, Integer(2), Integer(2), Fq)
>>> C
[2, 2, 1] linear Gabidulin code over GF(16)/GF(4)
dual_code()[source]

Return the dual code \(C^{\perp}\) of self, the code \(C\),

\[C^{\perp} = \{ v \in V\ |\ v\cdot c = 0,\ \forall c \in C \}.\]

EXAMPLES:

sage: C = codes.GabidulinCode(GF(2^10), 5, 2)
sage: C1 = C.dual_code(); C1
[5, 3, 3] linear Gabidulin code over GF(1024)/GF(2)
sage: C == C1.dual_code()
True
>>> from sage.all import *
>>> C = codes.GabidulinCode(GF(Integer(2)**Integer(10)), Integer(5), Integer(2))
>>> C1 = C.dual_code(); C1
[5, 3, 3] linear Gabidulin code over GF(1024)/GF(2)
>>> C == C1.dual_code()
True
evaluation_points()[source]

Return the evaluation points of self.

EXAMPLES:

sage: Fqm = GF(5^20)
sage: Fq = GF(5^4)
sage: C = codes.GabidulinCode(Fqm, 4, 4, Fq)
sage: C.evaluation_points()
[1, z20, z20^2, z20^3]
>>> from sage.all import *
>>> Fqm = GF(Integer(5)**Integer(20))
>>> Fq = GF(Integer(5)**Integer(4))
>>> C = codes.GabidulinCode(Fqm, Integer(4), Integer(4), Fq)
>>> C.evaluation_points()
[1, z20, z20^2, z20^3]
minimum_distance()[source]

Return the minimum distance of self.

Since Gabidulin Codes are Maximum-Distance-Separable (MDS), this returns

self.length() - self.dimension() + 1.

EXAMPLES:

sage: Fqm = GF(5^20)
sage: Fq = GF(5)
sage: C = codes.GabidulinCode(Fqm, 20, 15, Fq)
sage: C.minimum_distance()
6
>>> from sage.all import *
>>> Fqm = GF(Integer(5)**Integer(20))
>>> Fq = GF(Integer(5))
>>> C = codes.GabidulinCode(Fqm, Integer(20), Integer(15), Fq)
>>> C.minimum_distance()
6
parity_check_matrix()[source]

Return the parity check matrix of self.

This is the generator matrix of the dual code of self.

EXAMPLES:

sage: C = codes.GabidulinCode(GF(2^3), 3, 2)
sage: C.parity_check_matrix()
[        1        z3 z3^2 + z3]
sage: C.parity_check_matrix() == C.dual_code().generator_matrix()
True
>>> from sage.all import *
>>> C = codes.GabidulinCode(GF(Integer(2)**Integer(3)), Integer(3), Integer(2))
>>> C.parity_check_matrix()
[        1        z3 z3^2 + z3]
>>> C.parity_check_matrix() == C.dual_code().generator_matrix()
True
parity_evaluation_points()[source]

Return the parity evaluation points of self.

These form the first row of the parity check matrix of self.

EXAMPLES:

sage: C = codes.GabidulinCode(GF(2^10), 5, 2)
sage: list(C.parity_check_matrix().row(0)) == C.parity_evaluation_points() #indirect_doctest
True
>>> from sage.all import *
>>> C = codes.GabidulinCode(GF(Integer(2)**Integer(10)), Integer(5), Integer(2))
>>> list(C.parity_check_matrix().row(Integer(0))) == C.parity_evaluation_points() #indirect_doctest
True
twisting_homomorphism()[source]

Return the twisting homomorphism of self.

EXAMPLES:

sage: Fqm = GF(5^20)
sage: Fq = GF(5^4)
sage: C = codes.GabidulinCode(Fqm, 5, 3, Fq)
sage: C.twisting_homomorphism()
Frobenius endomorphism z20 |--> z20^(5^4) on Finite Field in z20 of size 5^20
>>> from sage.all import *
>>> Fqm = GF(Integer(5)**Integer(20))
>>> Fq = GF(Integer(5)**Integer(4))
>>> C = codes.GabidulinCode(Fqm, Integer(5), Integer(3), Fq)
>>> C.twisting_homomorphism()
Frobenius endomorphism z20 |--> z20^(5^4) on Finite Field in z20 of size 5^20
class sage.coding.gabidulin_code.GabidulinGaoDecoder(code)[source]

Bases: Decoder

Gao style decoder for Gabidulin Codes.

INPUT:

  • code – the associated code of this decoder

EXAMPLES:

sage: Fqm = GF(16)
sage: Fq = GF(4)
sage: C = codes.GabidulinCode(Fqm, 2, 2, Fq)
sage: D = codes.decoders.GabidulinGaoDecoder(C)
sage: D
Gao decoder for [2, 2, 1] linear Gabidulin code over GF(16)/GF(4)
>>> from sage.all import *
>>> Fqm = GF(Integer(16))
>>> Fq = GF(Integer(4))
>>> C = codes.GabidulinCode(Fqm, Integer(2), Integer(2), Fq)
>>> D = codes.decoders.GabidulinGaoDecoder(C)
>>> D
Gao decoder for [2, 2, 1] linear Gabidulin code over GF(16)/GF(4)

Alternatively, we can construct the encoder from C directly:

sage: D = C.decoder("Gao")
sage: D
Gao decoder for [2, 2, 1] linear Gabidulin code over GF(16)/GF(4)
>>> from sage.all import *
>>> D = C.decoder("Gao")
>>> D
Gao decoder for [2, 2, 1] linear Gabidulin code over GF(16)/GF(4)
decode_to_code(r)[source]

Return the decoded codeword corresponding to the received word \(r\).

INPUT:

  • r – received codeword

OUTPUT: the decoded codeword corresponding to the received codeword

EXAMPLES:

sage: Fqm = GF(3^20)
sage: Fq = GF(3)
sage: C = codes.GabidulinCode(Fqm, 5, 3, Fq)
sage: D = codes.decoders.GabidulinGaoDecoder(C)
sage: E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C)
sage: S.<x> = Fqm['x', C.twisting_homomorphism()]
sage: z20 = Fqm.gen()
sage: p = x
sage: codeword_vector = E.encode(p, "vector")
sage: codeword_vector
(1, z20^3, z20^6, z20^9, z20^12)
sage: l = list(codeword_vector)
sage: l[0] = l[1] #make an error
sage: D.decode_to_code(vector(l))
(1, z20^3, z20^6, z20^9, z20^12)
>>> from sage.all import *
>>> Fqm = GF(Integer(3)**Integer(20))
>>> Fq = GF(Integer(3))
>>> C = codes.GabidulinCode(Fqm, Integer(5), Integer(3), Fq)
>>> D = codes.decoders.GabidulinGaoDecoder(C)
>>> E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C)
>>> S = Fqm['x', C.twisting_homomorphism()]; (x,) = S._first_ngens(1)
>>> z20 = Fqm.gen()
>>> p = x
>>> codeword_vector = E.encode(p, "vector")
>>> codeword_vector
(1, z20^3, z20^6, z20^9, z20^12)
>>> l = list(codeword_vector)
>>> l[Integer(0)] = l[Integer(1)] #make an error
>>> D.decode_to_code(vector(l))
(1, z20^3, z20^6, z20^9, z20^12)
decode_to_message(r)[source]

Return the skew polynomial (message) corresponding to the received word \(r\).

INPUT:

  • r – received codeword

OUTPUT: the message corresponding to the received codeword

EXAMPLES:

sage: Fqm = GF(2^9)
sage: Fq = GF(2^3)
sage: C = codes.GabidulinCode(Fqm, 2, 2, Fq)
sage: D = codes.decoders.GabidulinGaoDecoder(C)
sage: E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C)
sage: S.<x> = Fqm['x', C.twisting_homomorphism()]
sage: z9 = Fqm.gen()
sage: p = (z9^6 + z9^4)*x + z9^2 + z9
sage: codeword_vector = E.encode(p, "vector")
sage: r = D.decode_to_message(codeword_vector)
sage: r
(z9^6 + z9^4)*x + z9^2 + z9
>>> from sage.all import *
>>> Fqm = GF(Integer(2)**Integer(9))
>>> Fq = GF(Integer(2)**Integer(3))
>>> C = codes.GabidulinCode(Fqm, Integer(2), Integer(2), Fq)
>>> D = codes.decoders.GabidulinGaoDecoder(C)
>>> E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C)
>>> S = Fqm['x', C.twisting_homomorphism()]; (x,) = S._first_ngens(1)
>>> z9 = Fqm.gen()
>>> p = (z9**Integer(6) + z9**Integer(4))*x + z9**Integer(2) + z9
>>> codeword_vector = E.encode(p, "vector")
>>> r = D.decode_to_message(codeword_vector)
>>> r
(z9^6 + z9^4)*x + z9^2 + z9
decoding_radius()[source]

Return the decoding radius of the Gabidulin Gao Decoder.

EXAMPLES:

sage: Fqm = GF(5^20)
sage: Fq = GF(5)
sage: C = codes.GabidulinCode(Fqm, 20, 4, Fq)
sage: D = codes.decoders.GabidulinGaoDecoder(C)
sage: D.decoding_radius()
8
>>> from sage.all import *
>>> Fqm = GF(Integer(5)**Integer(20))
>>> Fq = GF(Integer(5))
>>> C = codes.GabidulinCode(Fqm, Integer(20), Integer(4), Fq)
>>> D = codes.decoders.GabidulinGaoDecoder(C)
>>> D.decoding_radius()
8
class sage.coding.gabidulin_code.GabidulinPolynomialEvaluationEncoder(code)[source]

Bases: Encoder

Encoder for Gabidulin codes which uses evaluation of skew polynomials to obtain codewords.

Let \(C\) be a Gabidulin code of length \(n\) and dimension \(k\) over some finite field \(F = GF(q^m)\). We denote by \(\alpha_i\) its evaluations points, where \(1 \leq i \leq n\). Let \(p\), a skew polynomial of degree at most \(k-1\) in \(F[x]\), be the message.

The encoding of \(m\) will be the following codeword:

\[(p(\alpha_1), \dots, p(\alpha_n)).\]

EXAMPLES:

sage: Fqm = GF(16)
sage: Fq = GF(4)
sage: C = codes.GabidulinCode(Fqm, 2, 2, Fq)
sage: E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C)
sage: E
Polynomial evaluation style encoder for
 [2, 2, 1] linear Gabidulin code over GF(16)/GF(4)
>>> from sage.all import *
>>> Fqm = GF(Integer(16))
>>> Fq = GF(Integer(4))
>>> C = codes.GabidulinCode(Fqm, Integer(2), Integer(2), Fq)
>>> E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C)
>>> E
Polynomial evaluation style encoder for
 [2, 2, 1] linear Gabidulin code over GF(16)/GF(4)

Alternatively, we can construct the encoder from C directly:

sage: E = C.encoder("PolynomialEvaluation")
sage: E
Polynomial evaluation style encoder for
 [2, 2, 1] linear Gabidulin code over GF(16)/GF(4)
>>> from sage.all import *
>>> E = C.encoder("PolynomialEvaluation")
>>> E
Polynomial evaluation style encoder for
 [2, 2, 1] linear Gabidulin code over GF(16)/GF(4)
encode(p, form='vector')[source]

Transform the polynomial p into a codeword of code().

The output codeword can be represented as a vector or a matrix, depending on the form input.

INPUT:

  • p – a skew polynomial from the message space of self of degree less than self.code().dimension()

  • form – type parameter taking strings “vector” or “matrix” as values and converting the output codeword into the respective form (default: 'vector')

OUTPUT: a codeword corresponding to \(p\) in vector or matrix form

EXAMPLES:

sage: Fqm = GF(2^9)
sage: Fq = GF(2^3)
sage: C = codes.GabidulinCode(Fqm, 2, 2, Fq)
sage: E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C)
sage: S.<x> = Fqm['x', C.twisting_homomorphism()]
sage: z9 = Fqm.gen()
sage: p = (z9^6 + z9^2 + z9 + 1)*x + z9^7 + z9^5 + z9^4 + z9^2
sage: codeword_vector = E.encode(p, "vector"); codeword_vector
(z9^7 + z9^6 + z9^5 + z9^4 + z9 + 1, z9^6 + z9^5 + z9^3 + z9)
sage: codeword_matrix = E.encode(p, "matrix"); codeword_matrix
[           z3     z3^2 + z3]
[           z3             1]
[         z3^2 z3^2 + z3 + 1]
>>> from sage.all import *
>>> Fqm = GF(Integer(2)**Integer(9))
>>> Fq = GF(Integer(2)**Integer(3))
>>> C = codes.GabidulinCode(Fqm, Integer(2), Integer(2), Fq)
>>> E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C)
>>> S = Fqm['x', C.twisting_homomorphism()]; (x,) = S._first_ngens(1)
>>> z9 = Fqm.gen()
>>> p = (z9**Integer(6) + z9**Integer(2) + z9 + Integer(1))*x + z9**Integer(7) + z9**Integer(5) + z9**Integer(4) + z9**Integer(2)
>>> codeword_vector = E.encode(p, "vector"); codeword_vector
(z9^7 + z9^6 + z9^5 + z9^4 + z9 + 1, z9^6 + z9^5 + z9^3 + z9)
>>> codeword_matrix = E.encode(p, "matrix"); codeword_matrix
[           z3     z3^2 + z3]
[           z3             1]
[         z3^2 z3^2 + z3 + 1]
message_space()[source]

Return the message space of the associated code of self.

EXAMPLES:

sage: Fqm = GF(5^20)
sage: Fq = GF(5^4)
sage: C = codes.GabidulinCode(Fqm, 4, 4, Fq)
sage: E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C)
sage: E.message_space()
Ore Polynomial Ring in x over Finite Field in z20 of size 5^20
 twisted by z20 |--> z20^(5^4)
>>> from sage.all import *
>>> Fqm = GF(Integer(5)**Integer(20))
>>> Fq = GF(Integer(5)**Integer(4))
>>> C = codes.GabidulinCode(Fqm, Integer(4), Integer(4), Fq)
>>> E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C)
>>> E.message_space()
Ore Polynomial Ring in x over Finite Field in z20 of size 5^20
 twisted by z20 |--> z20^(5^4)
unencode_nocheck(c)[source]

Return the message corresponding to the codeword c.

Use this method with caution: it does not check if c belongs to the code, and if this is not the case, the output is unspecified.

INPUT:

  • c – a codeword of code()

OUTPUT:

  • a skew polynomial of degree less than self.code().dimension()

EXAMPLES:

sage: Fqm = GF(2^9)
sage: Fq = GF(2^3)
sage: C = codes.GabidulinCode(Fqm, 2, 2, Fq)
sage: E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C)
sage: S.<x> = Fqm['x', C.twisting_homomorphism()]
sage: z9 = Fqm.gen()
sage: p = (z9^6 + z9^4)*x + z9^2 + z9
sage: codeword_vector = E.encode(p, "vector")
sage: E.unencode_nocheck(codeword_vector)
(z9^6 + z9^4)*x + z9^2 + z9
>>> from sage.all import *
>>> Fqm = GF(Integer(2)**Integer(9))
>>> Fq = GF(Integer(2)**Integer(3))
>>> C = codes.GabidulinCode(Fqm, Integer(2), Integer(2), Fq)
>>> E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C)
>>> S = Fqm['x', C.twisting_homomorphism()]; (x,) = S._first_ngens(1)
>>> z9 = Fqm.gen()
>>> p = (z9**Integer(6) + z9**Integer(4))*x + z9**Integer(2) + z9
>>> codeword_vector = E.encode(p, "vector")
>>> E.unencode_nocheck(codeword_vector)
(z9^6 + z9^4)*x + z9^2 + z9
class sage.coding.gabidulin_code.GabidulinVectorEvaluationEncoder(code)[source]

Bases: Encoder

This method constructs the vector evaluation encoder for Gabidulin Codes.

INPUT:

  • code – the associated code of this encoder

EXAMPLES:

sage: Fqm = GF(16)
sage: Fq = GF(4)
sage: C = codes.GabidulinCode(Fqm, 2, 2, Fq)
sage: E = codes.encoders.GabidulinVectorEvaluationEncoder(C)
sage: E
Vector evaluation style encoder for [2, 2, 1] linear Gabidulin code over GF(16)/GF(4)
>>> from sage.all import *
>>> Fqm = GF(Integer(16))
>>> Fq = GF(Integer(4))
>>> C = codes.GabidulinCode(Fqm, Integer(2), Integer(2), Fq)
>>> E = codes.encoders.GabidulinVectorEvaluationEncoder(C)
>>> E
Vector evaluation style encoder for [2, 2, 1] linear Gabidulin code over GF(16)/GF(4)

Alternatively, we can construct the encoder from C directly:

sage: E = C.encoder("VectorEvaluation")
sage: E
Vector evaluation style encoder for [2, 2, 1] linear Gabidulin code over GF(16)/GF(4)
>>> from sage.all import *
>>> E = C.encoder("VectorEvaluation")
>>> E
Vector evaluation style encoder for [2, 2, 1] linear Gabidulin code over GF(16)/GF(4)
generator_matrix()[source]

Return the generator matrix of self.

EXAMPLES:

sage: Fqm = GF(2^9)
sage: Fq = GF(2^3)
sage: C = codes.GabidulinCode(Fqm, 3, 3, Fq)
sage: (list(C.generator_matrix().row(1))
....:   == [C.evaluation_points()[i]**(2**3) for i in range(3)])
True
>>> from sage.all import *
>>> Fqm = GF(Integer(2)**Integer(9))
>>> Fq = GF(Integer(2)**Integer(3))
>>> C = codes.GabidulinCode(Fqm, Integer(3), Integer(3), Fq)
>>> (list(C.generator_matrix().row(Integer(1)))
...   == [C.evaluation_points()[i]**(Integer(2)**Integer(3)) for i in range(Integer(3))])
True