Encoders

Representation of a bijection between a message space and a code.

AUTHORS:

  • David Lucas (2015): initial version

class sage.coding.encoder.Encoder(code)[source]

Bases: SageObject

Abstract top-class for Encoder objects.

Every encoder class for linear codes (of any metric) should inherit from this abstract class.

To implement an encoder, you need to:

  • inherit from Encoder,

  • call Encoder.__init__ in the subclass constructor. Example: super().__init__(code). By doing that, your subclass will have its code parameter initialized.

  • Then, if the message space is a vector space, default implementations of encode() and unencode_nocheck() methods are provided. These implementations rely on generator_matrix() which you need to override to use the default implementations.

  • If the message space is not of the form \(F^k\), where \(F\) is a finite field, you cannot have a generator matrix. In that case, you need to override encode(), unencode_nocheck() and message_space().

  • By default, comparison of Encoder (using methods __eq__ and __ne__ ) are by memory reference: if you build the same encoder twice, they will be different. If you need something more clever, override __eq__ and __ne__ in your subclass.

  • As Encoder is not designed to be instantiated, it does not have any representation methods. You should implement _repr_ and _latex_ methods in the subclass.

REFERENCES:

code()[source]

Return the code for this Encoder.

EXAMPLES:

sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0], [1,0,0,1,1,0,0],
....:                    [0,1,0,1,0,1,0], [1,1,0,1,0,0,1]])
sage: C = LinearCode(G)
sage: E = C.encoder()
sage: E.code() == C
True
>>> from sage.all import *
>>> G = Matrix(GF(Integer(2)), [[Integer(1),Integer(1),Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)], [Integer(1),Integer(0),Integer(0),Integer(1),Integer(1),Integer(0),Integer(0)],
...                    [Integer(0),Integer(1),Integer(0),Integer(1),Integer(0),Integer(1),Integer(0)], [Integer(1),Integer(1),Integer(0),Integer(1),Integer(0),Integer(0),Integer(1)]])
>>> C = LinearCode(G)
>>> E = C.encoder()
>>> E.code() == C
True
encode(word)[source]

Transform an element of the message space into a codeword.

This is a default implementation which assumes that the message space of the encoder is \(F^{k}\), where \(F\) is sage.coding.linear_code_no_metric.AbstractLinearCodeNoMetric.base_field() and \(k\) is sage.coding.linear_code_no_metric.AbstractLinearCodeNoMetric.dimension(). If this is not the case, this method should be overwritten by the subclass.

Note

encode() might be a partial function over self’s message_space(). One should use the exception EncodingError to catch attempts to encode words that are outside of the message space.

One can use the following shortcut to encode a word with an encoder E:

E(word)

INPUT:

  • word – a vector of the message space of the self

OUTPUT: a vector of code()

EXAMPLES:

sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0], [1,0,0,1,1,0,0],
....:                    [0,1,0,1,0,1,0], [1,1,0,1,0,0,1]])
sage: C = LinearCode(G)
sage: word = vector(GF(2), (0, 1, 1, 0))
sage: E = codes.encoders.LinearCodeGeneratorMatrixEncoder(C)
sage: E.encode(word)
(1, 1, 0, 0, 1, 1, 0)
>>> from sage.all import *
>>> G = Matrix(GF(Integer(2)), [[Integer(1),Integer(1),Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)], [Integer(1),Integer(0),Integer(0),Integer(1),Integer(1),Integer(0),Integer(0)],
...                    [Integer(0),Integer(1),Integer(0),Integer(1),Integer(0),Integer(1),Integer(0)], [Integer(1),Integer(1),Integer(0),Integer(1),Integer(0),Integer(0),Integer(1)]])
>>> C = LinearCode(G)
>>> word = vector(GF(Integer(2)), (Integer(0), Integer(1), Integer(1), Integer(0)))
>>> E = codes.encoders.LinearCodeGeneratorMatrixEncoder(C)
>>> E.encode(word)
(1, 1, 0, 0, 1, 1, 0)

If word is not in the message space of self, it will return an exception:

sage: word = random_vector(GF(7), 4)
sage: E.encode(word)
Traceback (most recent call last):
...
ValueError: The value to encode must be in
Vector space of dimension 4 over Finite Field of size 2
>>> from sage.all import *
>>> word = random_vector(GF(Integer(7)), Integer(4))
>>> E.encode(word)
Traceback (most recent call last):
...
ValueError: The value to encode must be in
Vector space of dimension 4 over Finite Field of size 2
generator_matrix()[source]

Return a generator matrix of the associated code of self.

This is an abstract method and it should be implemented separately. Reimplementing this for each subclass of Encoder is not mandatory (as a generator matrix only makes sense when the message space is of the \(F^k\), where \(F\) is the base field of code().)

EXAMPLES:

sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0], [1,0,0,1,1,0,0],
....:                    [0,1,0,1,0,1,0], [1,1,0,1,0,0,1]])
sage: C = LinearCode(G)
sage: E = C.encoder()
sage: E.generator_matrix()
[1 1 1 0 0 0 0]
[1 0 0 1 1 0 0]
[0 1 0 1 0 1 0]
[1 1 0 1 0 0 1]
>>> from sage.all import *
>>> G = Matrix(GF(Integer(2)), [[Integer(1),Integer(1),Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)], [Integer(1),Integer(0),Integer(0),Integer(1),Integer(1),Integer(0),Integer(0)],
...                    [Integer(0),Integer(1),Integer(0),Integer(1),Integer(0),Integer(1),Integer(0)], [Integer(1),Integer(1),Integer(0),Integer(1),Integer(0),Integer(0),Integer(1)]])
>>> C = LinearCode(G)
>>> E = C.encoder()
>>> E.generator_matrix()
[1 1 1 0 0 0 0]
[1 0 0 1 1 0 0]
[0 1 0 1 0 1 0]
[1 1 0 1 0 0 1]
message_space()[source]

Return the ambient space of allowed input to encode(). Note that encode() is possibly a partial function over the ambient space.

EXAMPLES:

sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0], [1,0,0,1,1,0,0],
....:                    [0,1,0,1,0,1,0], [1,1,0,1,0,0,1]])
sage: C = LinearCode(G)
sage: E = C.encoder()
sage: E.message_space()
Vector space of dimension 4 over Finite Field of size 2
>>> from sage.all import *
>>> G = Matrix(GF(Integer(2)), [[Integer(1),Integer(1),Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)], [Integer(1),Integer(0),Integer(0),Integer(1),Integer(1),Integer(0),Integer(0)],
...                    [Integer(0),Integer(1),Integer(0),Integer(1),Integer(0),Integer(1),Integer(0)], [Integer(1),Integer(1),Integer(0),Integer(1),Integer(0),Integer(0),Integer(1)]])
>>> C = LinearCode(G)
>>> E = C.encoder()
>>> E.message_space()
Vector space of dimension 4 over Finite Field of size 2
unencode(c, nocheck=False)[source]

Return the message corresponding to the codeword c.

This is the inverse of encode().

INPUT:

  • c – a codeword of code()

  • nocheck – boolean (default: False); checks if c is in code(). You might set this to True to disable the check for saving computation. Note that if c is not in self() and nocheck = True, then the output of unencode() is not defined (except that it will be in the message space of self).

OUTPUT: an element of the message space of self

EXAMPLES:

sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0], [1,0,0,1,1,0,0],
....:                    [0,1,0,1,0,1,0], [1,1,0,1,0,0,1]])
sage: C = LinearCode(G)
sage: c = vector(GF(2), (1, 1, 0, 0, 1, 1, 0))
sage: c in C
True
sage: E = codes.encoders.LinearCodeGeneratorMatrixEncoder(C)
sage: E.unencode(c)
(0, 1, 1, 0)
>>> from sage.all import *
>>> G = Matrix(GF(Integer(2)), [[Integer(1),Integer(1),Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)], [Integer(1),Integer(0),Integer(0),Integer(1),Integer(1),Integer(0),Integer(0)],
...                    [Integer(0),Integer(1),Integer(0),Integer(1),Integer(0),Integer(1),Integer(0)], [Integer(1),Integer(1),Integer(0),Integer(1),Integer(0),Integer(0),Integer(1)]])
>>> C = LinearCode(G)
>>> c = vector(GF(Integer(2)), (Integer(1), Integer(1), Integer(0), Integer(0), Integer(1), Integer(1), Integer(0)))
>>> c in C
True
>>> E = codes.encoders.LinearCodeGeneratorMatrixEncoder(C)
>>> E.unencode(c)
(0, 1, 1, 0)
unencode_nocheck(c)[source]

Return the message corresponding to c.

When c is not a codeword, the output is unspecified.

AUTHORS:

This function is taken from codinglib [Nie]

INPUT:

OUTPUT: an element of the message space of self

EXAMPLES:

sage: G = Matrix(GF(2), [[1,1,1,0,0,0,0], [1,0,0,1,1,0,0],
....:                    [0,1,0,1,0,1,0], [1,1,0,1,0,0,1]])
sage: C = LinearCode(G)
sage: c = vector(GF(2), (1, 1, 0, 0, 1, 1, 0))
sage: c in C
True
sage: E = codes.encoders.LinearCodeGeneratorMatrixEncoder(C)
sage: E.unencode_nocheck(c)
(0, 1, 1, 0)
>>> from sage.all import *
>>> G = Matrix(GF(Integer(2)), [[Integer(1),Integer(1),Integer(1),Integer(0),Integer(0),Integer(0),Integer(0)], [Integer(1),Integer(0),Integer(0),Integer(1),Integer(1),Integer(0),Integer(0)],
...                    [Integer(0),Integer(1),Integer(0),Integer(1),Integer(0),Integer(1),Integer(0)], [Integer(1),Integer(1),Integer(0),Integer(1),Integer(0),Integer(0),Integer(1)]])
>>> C = LinearCode(G)
>>> c = vector(GF(Integer(2)), (Integer(1), Integer(1), Integer(0), Integer(0), Integer(1), Integer(1), Integer(0)))
>>> c in C
True
>>> E = codes.encoders.LinearCodeGeneratorMatrixEncoder(C)
>>> E.unencode_nocheck(c)
(0, 1, 1, 0)

Taking a vector that does not belong to C will not raise an error but probably just give a non-sensical result:

sage: c = vector(GF(2), (1, 1, 0, 0, 1, 1, 1))
sage: c in C
False
sage: E = codes.encoders.LinearCodeGeneratorMatrixEncoder(C)
sage: E.unencode_nocheck(c)
(0, 1, 1, 0)
sage: m = vector(GF(2), (0, 1, 1, 0))
sage: c1 = E.encode(m)
sage: c == c1
False
>>> from sage.all import *
>>> c = vector(GF(Integer(2)), (Integer(1), Integer(1), Integer(0), Integer(0), Integer(1), Integer(1), Integer(1)))
>>> c in C
False
>>> E = codes.encoders.LinearCodeGeneratorMatrixEncoder(C)
>>> E.unencode_nocheck(c)
(0, 1, 1, 0)
>>> m = vector(GF(Integer(2)), (Integer(0), Integer(1), Integer(1), Integer(0)))
>>> c1 = E.encode(m)
>>> c == c1
False
exception sage.coding.encoder.EncodingError[source]

Bases: Exception

Special exception class to indicate an error during encoding or unencoding.