-
-
Notifications
You must be signed in to change notification settings - Fork 519
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merge of previous 'rank metric channel' enhancement #39117
base: develop
Are you sure you want to change the base?
Changes from all commits
abf97b8
d7b6180
eb704e8
fc12ce0
6bac54a
210f7b9
efd4312
57a616b
1974b89
ae52e87
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,10 +36,18 @@ | |
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` | ||
|
||
AUTHORS: | ||
|
||
- David Lucas (2015): initial version | ||
- Maxime Bombar (2021): Rank metric channel | ||
""" | ||
|
||
# **************************************************************************** | ||
# Copyright (C) 2015 David Lucas <[email protected]> | ||
# Copyright (C) 2021 Maxime Bombar <[email protected]> | ||
# | ||
# 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 | ||
|
@@ -49,15 +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.categories.cartesian_product import cartesian_product | ||
from sage.categories.fields import Fields | ||
from sage.functions.other import binomial | ||
from sage.matrix.constructor import matrix | ||
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.misc.abstract_method import abstract_method | ||
from sage.categories.cartesian_product import cartesian_product | ||
from sage.modules.free_module import VectorSpace | ||
from sage.arith.misc import binomial | ||
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): | ||
|
@@ -550,8 +560,8 @@ | |
|
||
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. | ||
|
@@ -816,3 +826,220 @@ | |
""" | ||
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 ambient space | ||
base_field. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
EXAMPLES: | ||
|
||
We construct a StaticRankErrorChannel which adds error of rank 2 | ||
to any transmitted message:: | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
sage: n_err = 2 | ||
sage: Chan = channels.StaticRankErrorChannel(GF(256)^6, n_err) | ||
sage: Chan | ||
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, 4) | ||
sage: Chan = channels.StaticRankErrorChannel(GF(256)^6, n_err) | ||
sage: Chan | ||
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): | ||
r""" | ||
TESTS: | ||
|
||
If the number of errors exceeds the dimension of the input space, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about r"""
Initialize.
TESTS: ? |
||
or the field extension degree, then an error is raised:: | ||
|
||
sage: n_err = 7 | ||
sage: channels.StaticRankErrorChannel(GF(256)^6, n_err) | ||
Traceback (most recent call last): | ||
... | ||
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:: | ||
|
||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
? |
||
if rank_errors[1] > space.dimension(): | ||
raise ValueError("There might be errors of rank larger than the dimension of the input space.") | ||
self._rank_errors = rank_errors | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
? |
||
self._base_field = space.base_field() | ||
if not relative_field: | ||
self._relative_field = self._base_field.prime_subfield() | ||
else: | ||
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): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
?
? |
||
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 | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
or
? |
||
def _repr_(self): | ||
r""" | ||
Return a string representation of ``self``. | ||
|
||
EXAMPLES:: | ||
|
||
sage: n_err = 2 | ||
sage: Chan = channels.StaticRankErrorChannel(GF(256)^6, n_err) | ||
sage: Chan | ||
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"\ | ||
% (format_interval(no_err), self._relative_field, self.input_space()) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
def _latex_(self): | ||
r""" | ||
Return a latex representation of ``self``. | ||
|
||
EXAMPLES:: | ||
|
||
sage: n_err = 2 | ||
sage: Chan = channels.StaticRankErrorChannel(GF(256)^6, n_err) | ||
sage: latex(Chan) | ||
\textnormal{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 "\\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()) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. a space before |
||
def transmit_unsafe(self, message): | ||
r""" | ||
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. | ||
|
||
This method does not check if ``message`` belongs to the input space of``self``. | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
INPUT: | ||
|
||
- ``message`` -- a vector | ||
|
||
OUTPUT: | ||
|
||
- a vector of the output space | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
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 | ||
""" | ||
rank_errors = randint(*self.rank_errors()) | ||
Fq = self._relative_field | ||
V = self._column_space | ||
n = self.input_space().dimension() | ||
good = False | ||
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) | ||
good = (M.rank() == rank_errors) | ||
e = vector(map(self._map_to_field, M.rows())) | ||
w = message + e | ||
return w | ||
|
||
def rank_errors(self): | ||
r""" | ||
Return the number of rank errors created by ``self``. | ||
|
||
EXAMPLES:: | ||
|
||
sage: n_err = 3 | ||
sage: Chan = channels.StaticRankErrorChannel(GF(256)^6, n_err) | ||
sage: Chan.rank_errors() | ||
(3, 3) | ||
""" | ||
return self._rank_errors | ||
|
||
def number_errors(self): | ||
r""" | ||
Return the number of errors created by ``self``. | ||
|
||
.. NOTE:: | ||
|
||
This function is here to ease the life of people coming from the Hamming world. | ||
|
||
EXAMPLES:: | ||
|
||
sage: n_err = 3 | ||
sage: Chan = channels.StaticRankErrorChannel(GF(256)^6, n_err) | ||
sage: Chan.number_errors() | ||
(3, 3) | ||
""" | ||
return self._rank_errors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
message. It can be
It can be either an integer or a tuple
?