From abf97b817ebb4618b8e5d9e629a5e03f696c3dad Mon Sep 17 00:00:00 2001 From: Maxime Bombar Date: Tue, 3 Aug 2021 18:04:53 +0200 Subject: [PATCH 1/7] [sage/coding] Add new channel: Rank metric static error channel --- src/sage/coding/channel.py | 215 +++++++++++++++++++++++++++- src/sage/coding/channels_catalog.py | 4 +- 2 files changed, 217 insertions(+), 2 deletions(-) diff --git a/src/sage/coding/channel.py b/src/sage/coding/channel.py index a8ab7c30e22..0499b61de0d 100644 --- a/src/sage/coding/channel.py +++ b/src/sage/coding/channel.py @@ -35,6 +35,8 @@ transmitted message - :class:`ErrorErasureChannel`, which creates a specific number of errors and a specific number of erasures in each transmitted message + - :class:`StaticRankErrorChannel`, which creates an error of specific rank in each + transmitted message. This is the rank analogue of :class:`StaticErrorRateChannel` """ # **************************************************************************** @@ -54,8 +56,11 @@ from sage.modules.free_module_element import vector from sage.misc.abstract_method import abstract_method from sage.categories.cartesian_product import cartesian_product -from sage.modules.free_module import VectorSpace +from sage.categories.fields import Fields +from sage.modules.free_module import VectorSpace, span from sage.functions.other import binomial +from sage.matrix.constructor import matrix +from sage.coding.linear_rank_metric import from_matrix_representation from copy import copy @@ -826,3 +831,211 @@ def probability_of_at_most_t_errors(self, t): """ return sum(self.probability_of_exactly_t_errors(i) for i in range(t+1)) + + +class StaticRankErrorChannel(Channel): + r""" + Channel which adds an error of static rank to each message it transmits. + + The input space and the output space of this channel are the same. + + INPUT: + + - ``space`` -- the space of both input and output + + - ``rank_errors`` -- the rank of the error added to each transmitted message + It can be either an integer of a tuple. If a tuple is passed as + argument, the rank of the error will be a random integer between the + two bounds of the tuple. + + - ``relative_field`` -- The field to which the extension is relative. + If not given, it will default to the prime_subfield of the ambiant space + base_field. + + EXAMPLES: + + We construct a StaticRankErrorChannel which adds error of rank 2 + to any transmitted message:: + + sage: n_err = 2 + sage: Chan = channels.StaticRankErrorChannel(GF(59)^40, n_err) + sage: Chan + Channel creating error of rank 2 over Finite Field of size 59, + of input and output space Vector space of dimension 40 + over Finite Field of size 59 + + We can also pass a tuple for the number of errors:: + + sage: n_err = (1, 10) + sage: Chan = channels.StaticRankErrorChannel(GF(59)^40, n_err) + sage: Chan + Channel creating error of rank between 1 and 10 over Finite Field + of size 59, of input and output space Vector space of dimension 40 + over Finite Field of size 59 + """ + + def __init__(self, space, rank_errors, relative_field = None): + r""" + TESTS: + + If the number of errors exceeds the dimension of the input space, + it will return an error:: + + sage: n_err = 42 + sage: Chan = channels.StaticRankErrorChannel(GF(59)^40, n_err) + Traceback (most recent call last): + ... + ValueError: There might be more errors than the dimension of the input space + + If ``relative_field`` is specified and is not a subfield of the base field, + it will return an error:: + + sage: n_err = 2 + sage: Chan = channels.StaticRankErrorChannel(GF(16)^6, n_err, GF(8)) + Traceback (most recent call last): + ... + ValueError: Finite Field in z4 of size 2^4 is not an extension of + Finite Field in z3 of size 2^3 + + If ``relative_field`` is specified and is not a field, + it will return an error:: + + sage: n_err = 2 + sage: Chan = channels.StaticRankErrorChannel(GF(16)^6, n_err, GF(4)^2) + Traceback (most recent call last): + ... + ValueError: relative_field must be a Field and + Vector space of dimension 2 over Finite Field in z2 + of size 2^2 is not. + """ + if isinstance(rank_errors, (Integer, int)): + rank_errors = (rank_errors, rank_errors) + if not isinstance(rank_errors, (tuple, list)): + raise ValueError("rank_errors must be a tuple, a list, an Integer or a Python int") + super(StaticRankErrorChannel, self).__init__(space, space) + if rank_errors[1] > space.dimension(): + raise ValueError("There might be more errors than the dimension of the input space") + self._rank_errors = rank_errors + self._base_field = space.base_field() + if not relative_field: + self._relative_field = self._base_field.prime_subfield() + else: + if not relative_field in Fields(): + raise ValueError("relative_field must be a Field and %s is not." % relative_field) + if not relative_field.is_subring(self._base_field): + raise ValueError("%s is not an extension of %s" % (self._base_field, relative_field)) + self._relative_field = relative_field + + def _repr_(self): + r""" + Return a string representation of ``self``. + + EXAMPLES:: + + sage: n_err = 2 + sage: Chan = channels.StaticRankErrorChannel(GF(59)^40, n_err) + sage: Chan + Channel creating error of rank 2 over Finite Field of size 59, + of input and output space Vector space of dimension 40 + over Finite Field of size 59 + """ + no_err = self.rank_errors() + return "Channel creating error of rank %s over %s, of input and output space %s"\ + % (format_interval(no_err), self._relative_field, self.input_space()) + + def _latex_(self): + r""" + Returns a latex representation of ``self``. + + EXAMPLES:: + + sage: n_err = 2 + sage: Chan = channels.StaticRankErrorChannel(GF(59)^40, n_err) + sage: latex(Chan) + \textnormal{Channel creating error of rank 2 over Finite Field + of size 59, of input and output space Vector space of dimension 40 + over Finite Field of size 59} + """ + no_err = self.rank_errors() + return "\\textnormal{Channel creating error of rank %s over %s, of input and output space %s}"\ + % (format_interval(no_err), self._relative_field, self.input_space()) + + def transmit_unsafe(self, message): + r""" + Returns ``message`` with as many errors as ``self._rank_errors`` in it. + + If ``self._rank_errors`` was passed as a tuple for the number of errors, it will + pick a random integer between the bounds of the tuple and use it as the number of errors. + + This method does not check if ``message`` belongs to the input space of``self``. + + INPUT: + + - ``message`` -- a vector + + OUTPUT: + + - a vector of the output space + + EXAMPLES:: + + sage: F = GF(16)^6 + sage: n_err = 2 + sage: Chan = channels.StaticRankErrorChannel(F, n_err, GF(4)) + sage: set_random_seed(10) + sage: msg = F.random_element() + sage: msg + (z4 + 1, z4, z4^3 + z4 + 1, z4^3 + z4^2 + z4 + 1, z4^2, z4^2) + sage: c = Chan.transmit_unsafe(msg) + + TESTS:: + + sage: from sage.coding.linear_rank_metric import rank_distance + sage: rank_distance(msg, c, GF(4)) + 2 + """ + w = copy(message) + rank_errors = randint(*self.rank_errors()) + Fqm = self._base_field + Fq = self._relative_field + V = Fqm.vector_space(Fq, map=False) + n = self.input_space().dimension() + good = False + w = None + while not good: + basis = [V.random_element() for i in range(rank_errors)] + R = span(basis) + err = [R.random_element() for i in range(n)] + M = matrix(Fq, err).transpose() + if M.rank() == rank_errors: + good = True + e = from_matrix_representation(M, Fqm) + w = message + e + return w + + def rank_errors(self): + r""" + Returns the number of rank errors created by ``self``. + + EXAMPLES:: + + sage: n_err = 3 + sage: Chan = channels.StaticRankErrorChannel(GF(59)^6, n_err) + sage: Chan.rank_errors() + (3, 3) + """ + return self._rank_errors + + def number_errors(self): + r""" + This function is here to ease the life of people comming from the Hamming world. + Returns the number of errors created by ``self``. + + EXAMPLES:: + + sage: n_err = 3 + sage: Chan = channels.StaticRankErrorChannel(GF(59)^6, n_err) + sage: Chan.number_errors() + (3, 3) + """ + return self._rank_errors diff --git a/src/sage/coding/channels_catalog.py b/src/sage/coding/channels_catalog.py index ed3aa0ce6c2..419194ce8d4 100644 --- a/src/sage/coding/channels_catalog.py +++ b/src/sage/coding/channels_catalog.py @@ -28,4 +28,6 @@ from sage.misc.lazy_import import lazy_import as _lazy_import _lazy_import('sage.coding.channel', ['ErrorErasureChannel', 'QarySymmetricChannel', - 'StaticErrorRateChannel']) + 'StaticErrorRateChannel', + 'StaticRankErrorChannel', + ]) From d7b6180a69eab670ea1f968c87518bed72e041d5 Mon Sep 17 00:00:00 2001 From: Maxime Bombar Date: Wed, 4 Aug 2021 15:21:40 +0200 Subject: [PATCH 2/7] [coding/channel] Patchbot compliance (blocks plugin). Also edit older code. --- src/sage/coding/channel.py | 41 ++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/sage/coding/channel.py b/src/sage/coding/channel.py index 0499b61de0d..438c63d9cba 100644 --- a/src/sage/coding/channel.py +++ b/src/sage/coding/channel.py @@ -372,7 +372,7 @@ def _repr_(self): def _latex_(self): r""" - Returns a latex representation of ``self``. + Return a latex representation of ``self``. EXAMPLES:: @@ -388,7 +388,7 @@ def _latex_(self): def transmit_unsafe(self, message): r""" - Returns ``message`` with as many errors as ``self._number_errors`` in it. + Return ``message`` with as many errors as ``self._number_errors`` in it. If ``self._number_errors`` was passed as a tuple for the number of errors, it will pick a random integer between the bounds of the tuple and use it as the number of errors. @@ -434,7 +434,7 @@ def transmit_unsafe(self, message): def number_errors(self): r""" - Returns the number of errors created by ``self``. + Return the number of errors created by ``self``. EXAMPLES:: @@ -527,7 +527,7 @@ def __init__(self, space, number_errors, number_erasures): def _repr_(self): r""" - Returns a string representation of ``self``. + Return a string representation of ``self``. EXAMPLES:: @@ -546,7 +546,7 @@ def _repr_(self): def _latex_(self): r""" - Returns a latex representation of ``self``. + Return a latex representation of ``self``. EXAMPLES:: @@ -565,7 +565,7 @@ def _latex_(self): def transmit_unsafe(self, message): r""" - Returns ``message`` with as many errors as ``self._number_errors`` in it, and as many erasures + Return ``message`` with as many errors as ``self._number_errors`` in it, and as many erasures as ``self._number_erasures`` in it. If ``self._number_errors`` was passed as an tuple for the number of errors, it will @@ -622,7 +622,7 @@ def transmit_unsafe(self, message): def number_errors(self): r""" - Returns the number of errors created by ``self``. + Return the number of errors created by ``self``. EXAMPLES:: @@ -635,7 +635,7 @@ def number_errors(self): def number_erasures(self): r""" - Returns the number of erasures created by ``self``. + Return the number of erasures created by ``self``. EXAMPLES:: @@ -718,7 +718,7 @@ def __init__(self, space, epsilon): def __repr__(self): r""" - Returns a string representation of ``self``. + Return a string representation of ``self``. EXAMPLES:: @@ -733,7 +733,7 @@ def __repr__(self): def _latex_(self): r""" - Returns a latex representation of ``self``. + Return a latex representation of ``self``. EXAMPLES:: @@ -748,7 +748,7 @@ def _latex_(self): def transmit_unsafe(self, message): r""" - Returns ``message`` where each of the symbols has been changed to another from the alphabet with + Return ``message`` where each of the symbols has been changed to another from the alphabet with probability :meth:`error_probability`. This method does not check if ``message`` belongs to the input space of``self``. @@ -781,7 +781,7 @@ def transmit_unsafe(self, message): def error_probability(self): r""" - Returns the error probability of a single symbol transmission of + Return the error probability of a single symbol transmission of ``self``. EXAMPLES:: @@ -795,7 +795,7 @@ def error_probability(self): def probability_of_exactly_t_errors(self, t): r""" - Returns the probability ``self`` has to return + Return the probability ``self`` has to return exactly ``t`` errors. INPUT: @@ -815,7 +815,7 @@ def probability_of_exactly_t_errors(self, t): def probability_of_at_most_t_errors(self, t): r""" - Returns the probability ``self`` has to return + Return the probability ``self`` has to return at most ``t`` errors. INPUT: @@ -945,7 +945,7 @@ def _repr_(self): def _latex_(self): r""" - Returns a latex representation of ``self``. + Return a latex representation of ``self``. EXAMPLES:: @@ -962,7 +962,7 @@ def _latex_(self): def transmit_unsafe(self, message): r""" - Returns ``message`` with as many errors as ``self._rank_errors`` in it. + Return ``message`` with as many errors as ``self._rank_errors`` in it. If ``self._rank_errors`` was passed as a tuple for the number of errors, it will pick a random integer between the bounds of the tuple and use it as the number of errors. @@ -1015,7 +1015,7 @@ def transmit_unsafe(self, message): def rank_errors(self): r""" - Returns the number of rank errors created by ``self``. + Return the number of rank errors created by ``self``. EXAMPLES:: @@ -1028,8 +1028,11 @@ def rank_errors(self): def number_errors(self): r""" - This function is here to ease the life of people comming from the Hamming world. - Returns the number of errors created by ``self``. + Return the number of errors created by ``self``. + + .. NOTE:: + + This function is here to ease the life of people comming from the Hamming world. EXAMPLES:: From eb704e83664c1030a3b49ab5452e442a54b4a828 Mon Sep 17 00:00:00 2001 From: Maxime Bombar Date: Fri, 6 Aug 2021 10:52:10 +0200 Subject: [PATCH 3/7] [sage/coding/channel] Fix typos --- src/sage/coding/channel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/coding/channel.py b/src/sage/coding/channel.py index 438c63d9cba..e0877403de2 100644 --- a/src/sage/coding/channel.py +++ b/src/sage/coding/channel.py @@ -849,7 +849,7 @@ class StaticRankErrorChannel(Channel): two bounds of the tuple. - ``relative_field`` -- The field to which the extension is relative. - If not given, it will default to the prime_subfield of the ambiant space + If not given, it will default to the prime_subfield of the ambient space base_field. EXAMPLES: @@ -1032,7 +1032,7 @@ def number_errors(self): .. NOTE:: - This function is here to ease the life of people comming from the Hamming world. + This function is here to ease the life of people coming from the Hamming world. EXAMPLES:: From fc12ce0d0f9b2c280060c0a46938fcc62999bf7d Mon Sep 17 00:00:00 2001 From: Maxime Bombar Date: Fri, 6 Aug 2021 10:52:30 +0200 Subject: [PATCH 4/7] [sage/coding/channel] Add AUTHORS block --- src/sage/coding/channel.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sage/coding/channel.py b/src/sage/coding/channel.py index e0877403de2..f44da5b304c 100644 --- a/src/sage/coding/channel.py +++ b/src/sage/coding/channel.py @@ -37,10 +37,16 @@ specific number of erasures in each transmitted message - :class:`StaticRankErrorChannel`, which creates an error of specific rank in each transmitted message. This is the rank analogue of :class:`StaticErrorRateChannel` + +AUTHORS: + + - David Lucas (2015): initial version + - Maxime Bombar (2021): Rank metric channel """ # **************************************************************************** # Copyright (C) 2015 David Lucas +# Copyright (C) 2021 Maxime Bombar # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by From 210f7b9b64125cf1d2fcc5a044e5eb00bd6b2a9b Mon Sep 17 00:00:00 2001 From: Julien Lavauzelle Date: Tue, 10 Dec 2024 20:47:34 +0100 Subject: [PATCH 5/7] Fix a bad requirement on the error rank + add more appropriate tests/examples --- src/sage/coding/channel.py | 67 +++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/src/sage/coding/channel.py b/src/sage/coding/channel.py index 871162e71f6..a6eeb9dfdef 100644 --- a/src/sage/coding/channel.py +++ b/src/sage/coding/channel.py @@ -855,20 +855,20 @@ class StaticRankErrorChannel(Channel): to any transmitted message:: sage: n_err = 2 - sage: Chan = channels.StaticRankErrorChannel(GF(59)^40, n_err) + sage: Chan = channels.StaticRankErrorChannel(GF(256)^6, n_err) sage: Chan - Channel creating error of rank 2 over Finite Field of size 59, - of input and output space Vector space of dimension 40 - over Finite Field of size 59 + Channel creating error of rank 2 over Finite Field of size 2, + of input and output space Vector space of dimension 6 + over Finite Field in z8 of size 2^8 We can also pass a tuple for the number of errors:: - sage: n_err = (1, 10) - sage: Chan = channels.StaticRankErrorChannel(GF(59)^40, n_err) + sage: n_err = (1, 4) + sage: Chan = channels.StaticRankErrorChannel(GF(256)^6, n_err) sage: Chan - Channel creating error of rank between 1 and 10 over Finite Field - of size 59, of input and output space Vector space of dimension 40 - over Finite Field of size 59 + Channel creating error of rank between 1 and 4 over Finite Field + of size 2, of input and output space Vector space of dimension 6 + over Finite Field in z8 of size 2^8 """ def __init__(self, space, rank_errors, relative_field = None): @@ -876,13 +876,17 @@ def __init__(self, space, rank_errors, relative_field = None): TESTS: If the number of errors exceeds the dimension of the input space, - it will return an error:: + or the field extension degree, then an error is raised:: - sage: n_err = 42 - sage: Chan = channels.StaticRankErrorChannel(GF(59)^40, n_err) + sage: n_err = 7 + sage: channels.StaticRankErrorChannel(GF(256)^6, n_err) Traceback (most recent call last): ... - ValueError: There might be more errors than the dimension of the input space + ValueError: There might be errors of rank larger than the dimension of the input space. + sage: channels.StaticRankErrorChannel(GF(64)^8, n_err) + Traceback (most recent call last): + ... + ValueError: There might be errors of rank larger than the field extension degree. If ``relative_field`` is specified and is not a subfield of the base field, it will return an error:: @@ -911,7 +915,7 @@ def __init__(self, space, rank_errors, relative_field = None): raise ValueError("rank_errors must be a tuple, a list, an Integer or a Python int") super(StaticRankErrorChannel, self).__init__(space, space) if rank_errors[1] > space.dimension(): - raise ValueError("There might be more errors than the dimension of the input space") + raise ValueError("There might be errors of rank larger than the dimension of the input space.") self._rank_errors = rank_errors self._base_field = space.base_field() if not relative_field: @@ -922,6 +926,12 @@ def __init__(self, space, rank_errors, relative_field = None): if not relative_field.is_subring(self._base_field): raise ValueError("%s is not an extension of %s" % (self._base_field, relative_field)) self._relative_field = relative_field + V, vec_to_field, field_to_vec = self._base_field.vector_space(self._relative_field) + self._column_space = V + self._extension_degree = V.dimension() + if rank_errors[1] > self._extension_degree: + raise ValueError("There might be errors of rank larger than the field extension degree.") + self._map_to_field = vec_to_field def _repr_(self): r""" @@ -930,11 +940,11 @@ def _repr_(self): EXAMPLES:: sage: n_err = 2 - sage: Chan = channels.StaticRankErrorChannel(GF(59)^40, n_err) + sage: Chan = channels.StaticRankErrorChannel(GF(256)^6, n_err) sage: Chan - Channel creating error of rank 2 over Finite Field of size 59, - of input and output space Vector space of dimension 40 - over Finite Field of size 59 + Channel creating error of rank 2 over Finite Field of size 2, + of input and output space Vector space of dimension 6 + over Finite Field in z8 of size 2^8 """ no_err = self.rank_errors() return "Channel creating error of rank %s over %s, of input and output space %s"\ @@ -947,11 +957,11 @@ def _latex_(self): EXAMPLES:: sage: n_err = 2 - sage: Chan = channels.StaticRankErrorChannel(GF(59)^40, n_err) + sage: Chan = channels.StaticRankErrorChannel(GF(256)^6, n_err) sage: latex(Chan) \textnormal{Channel creating error of rank 2 over Finite Field - of size 59, of input and output space Vector space of dimension 40 - over Finite Field of size 59} + of size 2, of input and output space Vector space of dimension 6 + over Finite Field in z8 of size 2^8} """ no_err = self.rank_errors() return "\\textnormal{Channel creating error of rank %s over %s, of input and output space %s}"\ @@ -991,22 +1001,19 @@ def transmit_unsafe(self, message): sage: rank_distance(msg, c, GF(4)) 2 """ - w = copy(message) rank_errors = randint(*self.rank_errors()) Fqm = self._base_field Fq = self._relative_field - V = Fqm.vector_space(Fq, map=False) + V = self._column_space n = self.input_space().dimension() good = False - w = None while not good: basis = [V.random_element() for i in range(rank_errors)] R = span(basis) err = [R.random_element() for i in range(n)] - M = matrix(Fq, err).transpose() - if M.rank() == rank_errors: - good = True - e = from_matrix_representation(M, Fqm) + M = matrix(Fq, err) + good = (M.rank() == rank_errors) + e = vector(map(self._map_to_field, M.rows())) w = message + e return w @@ -1017,7 +1024,7 @@ def rank_errors(self): EXAMPLES:: sage: n_err = 3 - sage: Chan = channels.StaticRankErrorChannel(GF(59)^6, n_err) + sage: Chan = channels.StaticRankErrorChannel(GF(256)^6, n_err) sage: Chan.rank_errors() (3, 3) """ @@ -1034,7 +1041,7 @@ def number_errors(self): EXAMPLES:: sage: n_err = 3 - sage: Chan = channels.StaticRankErrorChannel(GF(59)^6, n_err) + sage: Chan = channels.StaticRankErrorChannel(GF(256)^6, n_err) sage: Chan.number_errors() (3, 3) """ From efd4312a936f3c03633bdb7d416618b616985b4e Mon Sep 17 00:00:00 2001 From: Julien Lavauzelle Date: Tue, 10 Dec 2024 20:55:21 +0100 Subject: [PATCH 6/7] Replaced tests/examples with more general ones, including the use of StaticRankErrorChannel --- src/sage/coding/gabidulin_code.py | 42 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/sage/coding/gabidulin_code.py b/src/sage/coding/gabidulin_code.py index 3db66e4af7b..196a05bfe27 100644 --- a/src/sage/coding/gabidulin_code.py +++ b/src/sage/coding/gabidulin_code.py @@ -938,18 +938,19 @@ def _decode_to_code_and_message(self, r): EXAMPLES:: - sage: Fqm = GF(2^9) - sage: Fq = GF(2^3) - sage: C = codes.GabidulinCode(Fqm, 2, 2, Fq) + sage: Fqm = GF(5^12) + sage: Fq = GF(5) + sage: C = codes.GabidulinCode(Fqm, 11, 4, Fq) sage: D = codes.decoders.GabidulinGaoDecoder(C) sage: E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C) sage: S. = Fqm['x', C.twisting_homomorphism()] - sage: z9 = Fqm.gen() - sage: p = (z9^6 + z9^4)*x + z9^2 + z9 + sage: p = x**3 - x + 3 sage: codeword_vector = E.encode(p, "vector") - sage: r = D.decode_to_message(codeword_vector) #indirect doctest - sage: r - (z9^6 + z9^4)*x + z9^2 + z9 + sage: Chan = channels.StaticRankErrorChannel(C.ambient_space(), 3) + sage: y = Chan(codeword_vector) + sage: c, m = D._decode_to_code_and_message(y) + sage: c == codeword_vector and m == p + True """ C = self.code() length = len(r) @@ -960,7 +961,6 @@ def _decode_to_code_and_message(self, r): return r, self.connected_encoder().unencode_nocheck(r) points = [(eval_pts[i], r[i]) for i in range(len(eval_pts))] - # R = S.lagrange_polynomial(eval_pts, list(r)) R = S.lagrange_polynomial(points) r_out, u_out = self._partial_xgcd(S.minimal_vanishing_polynomial(eval_pts), R, (C.length() + C.dimension()) // 2) @@ -993,15 +993,12 @@ def decode_to_code(self, r): sage: D = codes.decoders.GabidulinGaoDecoder(C) sage: E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C) sage: S. = 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) + sage: Chan = channels.StaticRankErrorChannel(C.ambient_space(), 1) + sage: y = Chan(codeword_vector) + sage: D.decode_to_code(y) == codeword_vector + True """ return self._decode_to_code_and_message(r)[0] @@ -1018,18 +1015,19 @@ def decode_to_message(self, r): EXAMPLES:: - sage: Fqm = GF(2^9) + sage: Fqm = GF(2^18) sage: Fq = GF(2^3) - sage: C = codes.GabidulinCode(Fqm, 2, 2, Fq) + sage: C = codes.GabidulinCode(Fqm, 6, 2, Fq) sage: D = codes.decoders.GabidulinGaoDecoder(C) sage: E = codes.encoders.GabidulinPolynomialEvaluationEncoder(C) sage: S. = Fqm['x', C.twisting_homomorphism()] - sage: z9 = Fqm.gen() - sage: p = (z9^6 + z9^4)*x + z9^2 + z9 + sage: p = x + 1 sage: codeword_vector = E.encode(p, "vector") - sage: r = D.decode_to_message(codeword_vector) + sage: Chan = channels.StaticRankErrorChannel(C.ambient_space(), 2) + sage: y = Chan(codeword_vector) + sage: r = D.decode_to_message(y) sage: r - (z9^6 + z9^4)*x + z9^2 + z9 + x + 1 """ return self._decode_to_code_and_message(r)[1] From 57a616b3cb37ebcc0c83b48439007d903e34b185 Mon Sep 17 00:00:00 2001 From: Julien Lavauzelle Date: Tue, 10 Dec 2024 21:46:40 +0100 Subject: [PATCH 7/7] Fixed old/bad writing conventions --- src/sage/coding/channel.py | 25 +++++++++++-------------- src/sage/coding/channels_catalog.py | 1 + 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/sage/coding/channel.py b/src/sage/coding/channel.py index a6eeb9dfdef..217099081d1 100644 --- a/src/sage/coding/channel.py +++ b/src/sage/coding/channel.py @@ -57,19 +57,17 @@ # **************************************************************************** from copy import copy -from sage.structure.sage_object import SageObject -from sage.rings.integer import Integer -from sage.rings.finite_rings.finite_field_constructor import GF -from sage.misc.prandom import randint, random, sample -from sage.modules.free_module_element import vector -from sage.misc.abstract_method import abstract_method from sage.categories.cartesian_product import cartesian_product from sage.categories.fields import Fields -from sage.modules.free_module import VectorSpace, span from sage.functions.other import binomial from sage.matrix.constructor import matrix -from sage.coding.linear_rank_metric import from_matrix_representation -from copy import copy +from sage.misc.abstract_method import abstract_method +from sage.misc.prandom import randint, random, sample +from sage.modules.free_module import VectorSpace, span +from sage.modules.free_module_element import vector +from sage.rings.finite_rings.finite_field_constructor import GF +from sage.rings.integer import Integer +from sage.structure.sage_object import SageObject def random_error_vector(n, F, error_positions): @@ -562,8 +560,8 @@ def _latex_(self): def transmit_unsafe(self, message): r""" - Return ``message`` with as many errors as ``self._number_errors`` in it, - and as many erasures as ``self._number_erasures`` in it. + Return ``message`` with as many errors as ``self._number_errors`` + in it, and as many erasures as ``self._number_erasures`` in it. If ``self._number_errors`` was passed as a tuple for the number of errors, it will pick a random integer between the bounds of the tuple and use it as the number of errors. @@ -871,7 +869,7 @@ class StaticRankErrorChannel(Channel): over Finite Field in z8 of size 2^8 """ - def __init__(self, space, rank_errors, relative_field = None): + def __init__(self, space, rank_errors, relative_field=None): r""" TESTS: @@ -921,7 +919,7 @@ def __init__(self, space, rank_errors, relative_field = None): if not relative_field: self._relative_field = self._base_field.prime_subfield() else: - if not relative_field in Fields(): + if relative_field not in Fields(): raise ValueError("relative_field must be a Field and %s is not." % relative_field) if not relative_field.is_subring(self._base_field): raise ValueError("%s is not an extension of %s" % (self._base_field, relative_field)) @@ -1002,7 +1000,6 @@ def transmit_unsafe(self, message): 2 """ rank_errors = randint(*self.rank_errors()) - Fqm = self._base_field Fq = self._relative_field V = self._column_space n = self.input_space().dimension() diff --git a/src/sage/coding/channels_catalog.py b/src/sage/coding/channels_catalog.py index 80fe1622cde..248872eddf1 100644 --- a/src/sage/coding/channels_catalog.py +++ b/src/sage/coding/channels_catalog.py @@ -23,6 +23,7 @@ #***************************************************************************** from sage.misc.lazy_import import lazy_import as _lazy_import + _lazy_import('sage.coding.channel', ['ErrorErasureChannel', 'QarySymmetricChannel', 'StaticErrorRateChannel',