如何编写自己的编码理论类

本教程是为想要构建自己的类的高级用户设计的,将逐步解释您需要做什么来编写在编码理论框架内很好地集成的代码。在本教程中,我们将介绍以下部分:

  • 如何写出新的 code family

  • 如何写出新的 encoder

  • 如何写出新的 decoder

  • 如何写出新的 channel

本教程重点介绍重复代码的实现示例。在每个部分的最后,我们将对实施的每一个重要步骤进行总结。如果只想快速访问上面引用的某个对象的实现,可以直接跳到相关部分的末尾,这部分提供了要做什么的摘要。

一、抽象类

在Sage的编码模块中,有许多抽象类代表不同类型的代码。根据您要实现的代码类型,您应该从不同的抽象类继承。

The most generic class is sage.coding.abstract_code:AbstractCode. This class makes no assumptions about linearity, metric, finiteness or the number of alphabets. The abstract notion of "code" that is implicitly used for this class is any enumerable subset of a cartesian product A_1 times A_2 times ldots times A_n for some sets A_i.

例如,如果您想要创建一个非线性代码族,这就是您应该继承的类。

我们给出了一个创建非线性码族的小例子。以包含以下内容的代码为例 l 文字:

{00 ldots 00, 10 ldots 00, 11 ldots 00, ldots , 11 ldots 10, 11 ldots 11 }.

以下是我们如何实施它:

sage: from sage.coding.abstract_code import AbstractCode
sage: class ExampleCodeFamily(AbstractCode):
....:     def __init__(self, length):
....:         super(ExampleCodeFamily, self).__init__(length)
....:     def __iter__(self):
....:         for i in range(self.length() + 1):
....:             yield vector([1 for j in range(i)] + [0 for k in range(i, self.length())])
....:     def __contains__(self, word):
....:         return word in list(self)
....:     def _repr_(self):
....:         return "Dummy code of length {}".format(self.length())

sage: C = ExampleCodeFamily(4) # check that this works.
sage: C.list()
[(0, 0, 0, 0), (1, 0, 0, 0), (1, 1, 0, 0), (1, 1, 1, 0), (1, 1, 1, 1)]

关于线性码,最一般的代表是类 sage.coding.linear_code_no_metric:AbstractLinearCodeNoMetric 它包含所有线性码共享的所有方法,而不管它们的度量是什么。如果您想在某个度量上实现一个尚未在Sage中实现的线性代码,那么您应该继承这个类。

我们有两个特定于度量的抽象线性码类, sage.coding.linear_code:AbstractLinearCode 对于Hamming度量和 sage.coding.linear_rank_metric:AbstractLinearRankMetricCode 对于秩度量。如果您希望在这些指标之一上实现线性代码类,则应该从给定的抽象类继承。

二、重复码

我们想在Sage中实现众所周知的重复代码。其定义如下:

the \((n, 1)\)-repetition code over \(\GF{q}\) is the code formed by all the vectors of \(\GF{q}^{n}\) of the form \((i, i, i, \dots, i)\) for all \(i \in \GF{q}\).

例如, \((3, 1)\) -重复代码结束 \(\GF{2}\) 是: \(C = \{(0, 0, 0), (1, 1, 1)\}\)

编码很简单,只需重复一遍 \(n\) 将输入符号相乘,并拾取由此形成的矢量。

The decoding uses majority voting to select the right symbol (over \(\GF{2}\)). If we receive the word \((1, 0, 1)\) (example cont'd), we deduce that the original word was \((1)\). It can correct up to \(\left\lceil \frac{n-1}{2} \right\rceil\) errors.

通过本教程,我们将演示如何实现 \((n, 1)\) -重复代码结束 \(\GF{2}\)

编写新的代码类

编写新代码类的第一件事是确定要从哪个抽象类继承。由于重复代码是线性的,并且我们将其置于汉明度量之上,这意味着我们将从 sage.coding.linear_code.AbstractLinearCode

现在我们必须确定这个类的初始化参数,它们是:

  • 代码的长度,

  • 代码的基字段,

  • 代码的默认编码器,

  • 代码的默认解码器和

  • 我们希望在构造时设置的任何其他有用参数。

对于我们的代码,我们知道它的长度,它的尺寸,它的基域,一个编码器和一个解码器。

现在我们隔离了代码的参数,我们可以编写类的构造函数了。正如我们所说的,Hamming度量上的每个线性码类都必须继承自 sage.coding.linear_code.AbstractLinearCode 。此类提供了许多有用的方法,并且,正如我们在后面说明的,提供了一个默认构造函数,该构造函数设置 length vt.的. base field vt.的. default encoder 以及 default decoder 作为类参数。我们还需要为类创建已知编码器和解码器的词典。

现在让我们为我们的代码类编写构造函数,并将其存储在一个名为 repetition_code.py **

sage: from sage.coding.linear_code import AbstractLinearCode
sage: from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
sage: class BinaryRepetitionCode(AbstractLinearCode):
....:     _registered_encoders = {}
....:     _registered_decoders = {}
....:     def __init__(self, length):
....:         super(BinaryRepetitionCode, self).__init__(GF(2), length,
....:           "RepetitionGeneratorMatrixEncoder", "MajorityVoteDecoder")
....:         self._dimension = 1

正如您注意到的,构造函数非常简单。实际上,大多数工作都是由顶级类通过 super 陈述。注意,维度不是由抽象类设置的,因为对于某些代码族来说,准确的维度很难计算。如果已知确切的尺寸,请使用 _dimension 作为类参数。

我们现在可以为代码类编写表示方法::

sage: def _repr_(self):
....:     return "Binary repetition code of length %s" % self.length()
sage: def _latex_(self):
....:     return "\textnormal{Binary repetition code of length } %s" % self.length()

我们还编写了一个方法来检查相等性::

sage: def __eq__(self, other):
....:     return (isinstance(other, BinaryRepetitionCode)
....:             and self.length() == other.length()
....:             and self.dimension() == other.dimension())

在这些示例之后,您可能注意到我们使用了两种方法,即 length()dimension() 而不是定义它们。这是因为它们的实现是在 sage.coding.linear_code.AbstractLinearCode ,它们是 sage.coding.linear_code_no_metric.AbstractLinearCodeNoMetricsage.coding.abstract_code.AbstractCode

它们提供以下getter方法的默认实现:

  • sage.coding.abstract_code.AbstractCode.length()

  • sage.coding.linear_code_no_metric.AbstractLinearCodeNoMetric.dimension()

  • sage.coding.linear_code_no_metric.AbstractLinearCodeNoMetric.base_field()

  • sage.coding.linear_code_no_metric.AbstractLinearCodeNoMetric.ambient_space()

它们还提供了其他几种有用的方法,例如 __contains__ 。请注意,这些其他方法中的许多都依赖于生成矩阵的计算。因此,强烈建议将知道如何计算此类矩阵的编码器设置为默认编码器。因为所有这些需要生成矩阵的方法都将使用默认编码器,如果提供的默认编码器没有 generator_matrix 方法,很多泛型方法都会失败。

因为我们的代码族非常简单,所以我们不需要任何其他东西,并且上面提供的代码足以正确地描述重复代码。

Hamming度量上线性码的实现综述

  1. 继承自 sage.coding.linear_code.AbstractLinearCode

  2. 增列 _registered_encoders =  {}_registered_decoders = {} 作为类变量。

  3. 在类的构造函数中添加以下行::

    super(ClassName, self).__init__(base_field, length, "DefaultEncoder", "DefaultDecoder")
    
  4. 实现表示方法(不是强制的,但强烈建议) _repr__latex_

  5. 实施 __eq__

  6. __ne__lengthdimension 和抽象类一起来吧。

请注意 dimension 如果没有田地,就不会起作用 _dimension 作为类参数。

我们现在知道如何编写新的代码类。让我们看看如何编写一个新的编码器和一个新的解码器。

IV.编写一个新的编码器类

让我们继续我们的例子。我们像以前一样问同样的问题:我们需要用什么来描述编码器?对于大多数情况(包括本例),我们只需要相关的代码。在这种情况下,编写构造函数非常简单(我们将代码存储在相同的 .py 文件作为代码类)::

sage: from sage.coding.encoder import Encoder
sage: class BinaryRepetitionCodeGeneratorMatrixEncoder(Encoder):
....:     def __init__(self, code):
....:         super(BinaryRepetitionCodeGeneratorMatrixEncoder, self).__init__(code)

和以前一样,因为编码器总是需要知道它的相关代码,所以这项工作可以由基类来完成。记住要继承自 sage.coding.encoder.Encoder 好了!

我们还希望重写表示方法 _repr__latex_ **

sage: def _repr_(self):
....:     return "Binary repetition encoder for the %s" % self.code()
sage: def _latex_(self):
....:     return "\textnormal{Binary repetition encoder for the } %s" % self.code()

我们也希望有一个平等的检查::

sage: def __eq__(self, other):
....:     return (isinstance(other, BinaryRepetitionCodeGeneratorMatrixEncoder)
....:             and self.code() == other.code())

与前面一样,默认的getter方法由top类提供,即 sage.coding.encoder.Encoder.code()

我们所要做的就是实现与编码相关的方法。无论我们有没有生成矩阵,这个实现都会有很大的变化。

我们有一个生成器矩阵

在这种情况下,消息空间是一个向量空间,它特别简单:您需要实现的唯一方法是 generator_matrix

继续我们的示例,它将是:

sage: def generator_matrix(self):
....:     n = self.code().length()
....:     return Matrix(GF(2), 1, n, [GF(2).one()] * n)

因为top类为编码和逆操作提供了默认实现,所以我们称之为 unencode (请参阅: sage.coding.encoder.Encoder.encode()sage.coding.encoder.Encoder.unencode() ),以及默认实现 sage.coding.encoder.Encoder.message_space() ,我们在这里的工作已经完成。

备注

默认 encode 方法将提供的单词乘以生成矩阵,而默认情况下 unencode 计算生成矩阵的信息集,求逆并执行矩阵-向量乘法以恢复原始消息。如果有针对特定代码族的更好实现,则显然应该覆盖缺省值 encodeunencode

我们没有任何生成矩阵

在这种情况下,我们需要覆盖几个方法,即 encodeunencode_nocheck 而且很可能 message_space (在消息空间不是向量空间的情况下)。请注意,的默认实现 sage.coding.encoder.Encoder.unencode() 依赖于 unencode_nocheck ,因此没有必要重新实施前者。

在我们的示例中,很容易创建一个编码器,它不需要生成矩阵来执行编码和解编码。我们建议实施以下措施:

sage: def encode(self, message):
....:     return vector(GF(2), [message] * self.code().length())

sage: def unencode_nocheck(self, word):
....:     return word[0]

sage: def message_space(self):
....:     return GF(2)

我们在这里的工作已经完成了。

我们还需要做一件额外的事情:在相关代码类的已知编码器词典中设置此编码器。为此,只需在文件末尾添加以下行:

BinaryRepetitionCode._registered_encoders["RepetitionGeneratorMatrixEncoder"] = BinaryRepetitionCodeGeneratorMatrixEncoder

备注

如果您正在实现通用编码器(使用任何线性码族的编码器),请将以下语句添加到 AbstractLinearCode 的构造函数: self._registered_encoders["EncName"] = MyGenericEncoder 。这将使它立即可用于任何从 AbstractLinearCode

编码器实施情况摘要

  1. 继承自 sage.coding.encoder.Encoder

  2. 在类的构造函数中添加以下行::

    super(ClassName, self).__init__(associated_code)
    
  3. 实现表示方法(非强制) _repr__latex_

  4. 实施 __eq__

  5. __ne__code 和抽象类一起来吧。

  6. 如果已知生成矩阵,则重写 generator_matrix

  7. Else覆盖 encodeunencode_nocheck 如果需要的话, message_space

  8. 将编码器添加到 CodeClass._registered_encoders

V.编写新的解码器类

让我们继续编写一个解码器。和以前一样,我们需要知道描述解码器需要什么。我们当然需要解码器的相关代码。我们还想知道是哪一个 Encoder 当我们试图从包含错误的接收单词中恢复原始消息时,我们应该使用。我们称这个为编码器 connected_encoder 。由于不同的译码算法具有不同的行为(例如,概率译码与确定性译码),我们想给出一些关于译码器类型的线索。因此,我们可以在类参数中存储关键字列表 _decoder_type 。最终,我们还需要知道解码器的输入空间。通常,可以将这些参数的初始化委托给top类,我们的构造函数如下所示::

sage: from sage.coding.decoder import Decoder
sage: class BinaryRepetitionCodeMajorityVoteDecoder(Decoder):
....:     def __init__(self, code):
....:         super((BinaryRepetitionCodeMajorityVoteDecoder, self).__init__(code,
....:            code.ambient_space(), "RepetitionGeneratorMatrixEncoder"))

记住要继承自 sage.coding.decoder.Decoder 好了!

AS _decoder_type 实际上是一个类参数,所以应该在文件本身中设置它,而不是在任何方法之外。为了可读性,我们建议在文件底部添加此语句。我们稍后会回到这个问题上。

我们还希望重写表示方法 _repr__latex_ **

sage: def _repr_(self):
....:     return "Majority vote-based decoder for the %s" % self.code()
sage: def _latex_(self):
....:     return "\textnormal{Majority vote based-decoder for the } %s" % self.code()

我们也希望有一个平等的检查::

sage: def __eq__(self, other):
....:     return isinstance((other, BinaryRepetitionCodeMajorityVoteDecoder)
....:           and self.code() == other.code())

与前面一样,默认的getter方法由top类提供,即 sage.coding.decoder.Decoder.code()sage.coding.decoder.Decoder.input_space()sage.coding.decoder.Decoder.decoder_type()sage.coding.decoder.Decoder.connected_encoder()

我们所要做的就是实现与解码相关的方法。

有两种方法,即 sage.coding.decoder.Decoder.decode_to_code()sage.coding.decoder.Decoder.decode_to_message()

通过默认实现的魔力,这两者被链接在一起,就像 decode_to_message 呼叫优先 decode_to_code 然后 unencode ,而 decode_to_code 接连调用 decode_to_messageencode 。所以我们只需要实现这两个中的一个,我们选择重写 decode_to_code **

sage: def decode_to_code(self, word):
....:     list_word = word.list()
....:     count_one = list_word.count(GF(2).one())
....:     n = self.code().length()
....:     length = len(list_word)
....:     F = GF(2)
....:     if count_one > length / 2:
....:         return vector(F, [F.one()] * n)
....:     elif count_one < length / 2:
....:         return vector(F, [F.zero()] * n)
....:     else:
....:         raise DecodingError("impossible to find a majority")

备注

人们注意到,如果违约 decode_to_code 呼叫默认为 decode_to_message 和默认设置 decode_to_message 呼叫默认为 decode_to_code ,如果没有一个被重写,并且调用了一个,它将最终陷入无限循环。我们添加了一个触发器保护来防止这一点,因此如果没有一个被重写并且调用了一个,则将引发异常。

只缺少一种方法:一种向用户提供我们的解码器可以解码的错误数量的方法。这就是方法 sage.coding.decoder.Decoder.decoding_radius() ,我们将覆盖它:

sage: def decoding_radius(self):
....:     return (self.code().length()-1) // 2

对于某些情况,解码可能不是确切知道的,它的实现在 sage.coding.decoder.Decoder 的子类。

我们还需要做一件额外的事情:在相关代码类的已知解码器词典中设置此编码器。为此,只需在文件末尾添加以下行:

BinaryRepetitionCode._registered_decoders["MajorityVoteDecoder"] = BinaryRepetitionCodeMajorityVoteDecoder

也把这一行设置为 decoder_type **

BinaryRepetitionCode._decoder_type = {"hard-decision", "unique"}

备注

如果您正在实现通用解码器(与任何线性码系列一起工作的解码器),请在 AbstractLinearCode 的构造函数: self._registered_decoders["DecName"] = MyGenericDecoder 。这将使它立即可用于任何从 AbstractLinearCode

解码器的实现概述

  1. 继承自 sage.coding.decoder.Decoder

  2. 在类的构造函数中添加以下行::

    super(ClassName, self).__init__(associated_code, input_space, connected_encoder_name, decoder_type)
    
  3. 实现表示方法(非强制) _repr__latex_

  4. 实施 __eq__

  5. __ne__codeconnected_encoderdecoder_type 和抽象类一起来吧。

  6. 超覆 decode_to_codedecode_to_messagedecoding_radius

  7. 将编码器添加到 CodeClass._registered_decoders

VI.编写新的通道类

除了所有这些与代码直接相关的新结构之外,我们还提出了一种全新的闪亮结构来对代码进行实验,更具体地说,是关于它们的译码。

事实上,我们实现了一种模仿真实世界交流渠道的结构。

例如,我将在这里建议一种虚拟通道的逐步实现。

我们将实现一个非常幼稚的通道,它只为单词Over工作 \(\GF{2}\) 并根据用户的请求翻转任意数量的位。

由于频道与代码族没有直接关系,而是更多地与矢量和单词相关,所以我们有一个特定的文件, channel.py 用来储存它们。

因此,我们将在该文件中添加我们的新类。

首先,我们问自己一个永恒的问题:我们需要什么来描述一个渠道?嗯,我们迫切需要它 input_space 以及它的 output_space 。当然,在大多数情况下,用户将能够提供有关频道行为的一些额外信息。在我们的例子中,它将是要翻转的位数(也就是错误数)。

正如您可能已经猜到的那样,有一个抽象类来处理强制参数!另外,在我们的例子中,因为此通道仅适用于向量 \(\GF{2}\) ,输入和输出空间是相同的。让我们编写新通道类的构造函数::

sage: from sage.coding.channel import Channel
sage: class BinaryStaticErrorRateChannel(Channel):
....:     def __init__(self, space, number_errors):
....:         if space.base_ring() is not GF(2):
....:             raise ValueError("Provided space must be a vector space over GF(2)")
....:         if number_errors > space.dimension():
....:             raise ValueErrors("number_errors cannot be bigger than input space's dimension")
....:         super(BinaryStaticErrorRateChannel, self).__init__(space, space)
....:         self._number_errors = number_errors

记住要继承自 sage.coding.channel.Channel 好了!

我们还希望重写表示方法 _repr__latex_ **

sage: def _repr_(self):
....:     return ("Binary static error rate channel creating %s errors, of input and output space %s"
....:             % (format_interval(no_err), self.input_space()))

sage: def _latex_(self):
....:     return ("\\textnormal{Static error rate channel creating %s errors, of input and output space %s}"
....:             % (format_interval(no_err), self.input_space()))

我们并没有真正看到相等方法的任何用例 (__eq____ne__ ),因此不提供任何默认实现。如果需要这些方法,当然可以覆盖Python的默认方法。

我们当然希望使用getter方法。提供了一个默认实现 input_spaceoutput_space ,所以我们只需要一个 number_errors **

sage: def number_errors(self):
....:     return self._number_errors

所以,现在我们需要一种方法来向单词中实际添加错误。由于这与在真实世界的通道上传输消息相同,因此我们提出两种方法, transmittransmit_unsafe 。正如你可以猜到的, transmit_unsafe 尝试在不检查消息是否在输入空间中的情况下传输消息,而 transmit 在传输前检查这个。这意味着 transmit 有一个默认实现,它调用 transmit_unsafe 。所以我们只需要覆盖 transmit_unsafe 好了!让我们来做吧::

sage: def transmit_unsafe(self, message):
....:     w = copy(message)
....:     number_err = self.number_errors()
....:     V = self.input_space()
....:     F = GF(2)
....:     for i in sample(range(V.dimension()), number_err):
....:         w[i] += F.one()
....:     return w

就是这样,我们现在有了新的通道类可以使用了!

渠道实施情况总结

  1. 继承自 sage.coding.channel.Channel

  2. 在类的构造函数中添加以下行:

    super(ClassName, self).__init__(input_space, output_space)
    
  3. 实现表示方法(非强制) _repr__latex_

  4. input_spaceoutput_space Getter方法随抽象类一起提供。

  5. 超覆 transmit_unsafe

七、对新元素进行排序

由于编码理论库中有许多代码族和通道,我们不希望将所有类直接存储在Sage的全局命名空间中。

我们建议使用几个目录文件来存储我们的构造,即:

  • codes_catalog.py,

  • encoders_catalog.py,

  • decoders_catalog.py

  • channels_catalog.py.

每次创建新对象时,应将其添加到专用目录文件中,而不是对理论文件夹的 all.py

在这里,它指的是:

  • 添加以下内容 codes_catalog.py

    from sage.coding.repetition_code import BinaryRepetitionCode
    
  • 添加以下内容 encoders_catalog.py

    from sage.coding.repetition_code import BinaryRepetitionCodeGeneratorMatrixEncoder
    
  • 添加以下内容 decoders_catalog.py

    from sage.coding.repetition_code import BinaryRepetitionCodeMajorityVoteDecoder
    
  • 添加以下内容 channels_catalog.py

    from sage.coding.channel import BinaryStaticErrorRateChannel
    

本教程的完整代码

如果您需要从一些基本代码开始,可以随意复制粘贴并从后面的代码派生。

repetition_code.py (带有两个编码器):

from sage.coding.linear_code import AbstractLinearCode
from sage.coding.encoder import Encoder
from sage.coding.decoder import Decoder
from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF

class BinaryRepetitionCode(AbstractLinearCode):

    _registered_encoders = {}
    _registered_decoders = {}

    def __init__(self, length):
        super(BinaryRepetitionCode, self).__init__(GF(2), length, "RepetitionGeneratorMatrixEncoder", "MajorityVoteDecoder")
        self._dimension = 1

    def _repr_(self):
        return "Binary repetition code of length %s" % self.length()

    def _latex_(self):
        return "\textnormal{Binary repetition code of length } %s" % self.length()

    def __eq__(self, other):
        return (isinstance(other, BinaryRepetitionCode)
           and self.length() == other.length()
           and self.dimension() == other.dimension())



class BinaryRepetitionCodeGeneratorMatrixEncoder(Encoder):

    def __init__(self, code):
        super(BinaryRepetitionCodeGeneratorMatrixEncoder, self).__init__(code)

    def _repr_(self):
        return "Binary repetition encoder for the %s" % self.code()

    def _latex_(self):
        return "\textnormal{Binary repetition encoder for the } %s" % self.code()

    def __eq__(self, other):
        return (isinstance(other, BinaryRepetitionCodeGeneratorMatrixEncoder)
           and self.code() == other.code())

    def generator_matrix(self):
        n = self.code().length()
        return Matrix(GF(2), 1, n, [GF(2).one()] * n)



class BinaryRepetitionCodeStraightforwardEncoder(Encoder):

    def __init__(self, code):
        super(BinaryRepetitionCodeStraightforwardEncoder, self).__init__(code)

    def _repr_(self):
        return "Binary repetition encoder for the %s" % self.code()

    def _latex_(self):
        return "\textnormal{Binary repetition encoder for the } %s" % self.code()

    def __eq__(self, other):
        return (isinstance(other, BinaryRepetitionCodeStraightforwardEncoder)
           and self.code() == other.code())

    def encode(self, message):
        return vector(GF(2), [message] * self.code().length())

    def unencode_nocheck(self, word):
        return word[0]

    def message_space(self):
        return GF(2)



class BinaryRepetitionCodeMajorityVoteDecoder(Decoder):

    def __init__(self, code):
        super(BinaryRepetitionCodeMajorityVoteDecoder, self).__init__(code, code.ambient_space(),
           "RepetitionGeneratorMatrixEncoder")

    def _repr_(self):
        return "Majority vote-based decoder for the %s" % self.code()

    def _latex_(self):
        return "\textnormal{Majority vote based-decoder for the } %s" % self.code()


    def __eq__(self, other):
        return (isinstance(other, BinaryRepetitionCodeMajorityVoteDecoder)
           and self.code() == other.code())

    def decode_to_code(self, word):
        list_word = word.list()
        count_one = list_word.count(GF(2).one())
        n = self.code().length()
        length = len(list_word)
        F = GF(2)
        if count_one > length / 2:
            return vector(F, [F.one()] * n)
        elif count_one < length / 2:
           return vector(F, [F.zero()] * n)
        else:
           raise DecodingError("impossible to find a majority")

    def decoding_radius(self):
        return (self.code().length()-1) // 2



BinaryRepetitionCode._registered_encoders["RepetitionGeneratorMatrixEncoder"] = BinaryRepetitionCodeGeneratorMatrixEncoder
BinaryRepetitionCode._registered_encoders["RepetitionStraightforwardEncoder"] = BinaryRepetitionCodeStraightforwardEncoder
BinaryRepetitionCode._registered_decoders["MajorityVoteDecoder"] = BinaryRepetitionCodeMajorityVoteDecoder
BinaryRepetitionCodeMajorityVoteDecoder._decoder_type = {"hard-decision", "unique"}

channel.py (续):

class BinaryStaticErrorRateChannel(Channel):

    def __init__(self, space, number_errors):
        if space.base_ring() is not GF(2):
            raise ValueError("Provided space must be a vector space over GF(2)")
        if number_errors > space.dimension():
            raise ValueErrors("number_errors cannot be bigger than input space's dimension")
        super(BinaryStaticErrorRateChannel, self).__init__(space, space)
        self._number_errors = number_errors

    def _repr_(self):
      return ("Binary static error rate channel creating %s errors, of input and output space %s"
              % (format_interval(no_err), self.input_space()))

    def _latex_(self):
      return ("\\textnormal{Static error rate channel creating %s errors, of input and output space %s}"
              % (format_interval(no_err), self.input_space()))

    def number_errors(self):
      return self._number_errors

    def transmit_unsafe(self, message):
        w = copy(message)
        number_err = self.number_errors()
        V = self.input_space()
        F = GF(2)
        for i in sample(range(V.dimension()), number_err):
            w[i] += F.one()
        return w

codes_catalog.py (续):

from sage.coding.repetition_code import BinaryRepetitionCode

encoders_catalog.py (续):

from sage.coding.repetition_code import (BinaryRepetitionCodeGeneratorMatrixEncoder, BinaryRepetitionCodeStraightforwardEncoder)

decoders_catalog.py (续):

from sage.coding.repetition_code import BinaryRepetitionCodeMajorityVoteDecoder

channels_catalog.py (续):

from sage.coding.channel import (ErrorErasureChannel, StaticErrorRateChannel, BinaryStaticErrorRateChannel)