Channels¶
Given an input space and an output space, a channel takes element from the input space (the message) and transforms it into an element of the output space (the transmitted message).
In Sage, Channels simulate error-prone transmission over communication channels, and we borrow the nomenclature from communication theory, such as “transmission” and “positions” as the elements of transmitted vectors. Transmission can be achieved with two methods:
- Channel.transmit(). Considering a channel- Chanand a message- msg, transmitting- msgwith- Chancan be done this way:- Chan.transmit(msg)- It can also be written in a more convenient way: - Chan(msg)
- transmit_unsafe(). This does the exact same thing as- transmit()except that it does not check if- msgbelongs to the input space of- Chan:- Chan.transmit_unsafe(msg)
This is useful in e.g. an inner-loop of a long simulation as a
lighter-weight alternative to Channel.transmit().
This file contains the following elements:
Channel, the abstract class for Channels
StaticErrorRateChannel, which creates a specific number of errors in each transmitted message
ErrorErasureChannel, which creates a specific number of errors and a specific number of erasures in each transmitted message
- class sage.coding.channel.Channel(input_space, output_space)[source]¶
- Bases: - SageObject- Abstract top-class for Channel objects. - All channel objects must inherit from this class. To implement a channel subclass, one should do the following: - inherit from this class, 
- call the super constructor, 
- override - transmit_unsafe().
 - While not being mandatory, it might be useful to reimplement representation methods ( - _repr_and- _latex_).- This abstract class provides the following parameters: - input_space– the space of the words to transmit
- output_space– the space of the transmitted words
 - input_space()[source]¶
- Return the input space of - self.- EXAMPLES: - sage: n_err = 2 sage: Chan = channels.StaticErrorRateChannel(GF(59)^6, n_err) sage: Chan.input_space() Vector space of dimension 6 over Finite Field of size 59 - >>> from sage.all import * >>> n_err = Integer(2) >>> Chan = channels.StaticErrorRateChannel(GF(Integer(59))**Integer(6), n_err) >>> Chan.input_space() Vector space of dimension 6 over Finite Field of size 59 
 - output_space()[source]¶
- Return the output space of - self.- EXAMPLES: - sage: n_err = 2 sage: Chan = channels.StaticErrorRateChannel(GF(59)^6, n_err) sage: Chan.output_space() Vector space of dimension 6 over Finite Field of size 59 - >>> from sage.all import * >>> n_err = Integer(2) >>> Chan = channels.StaticErrorRateChannel(GF(Integer(59))**Integer(6), n_err) >>> Chan.output_space() Vector space of dimension 6 over Finite Field of size 59 
 - transmit(message)[source]¶
- Return - message, modified accordingly with the algorithm of the channel it was transmitted through.- Checks if - messagebelongs to the input space, and returns an exception if not. Note that- messageitself is never modified by the channel.- INPUT: - message– a vector
 - OUTPUT: a vector of the output space of - self- EXAMPLES: - sage: F = GF(59)^6 sage: n_err = 2 sage: Chan = channels.StaticErrorRateChannel(F, n_err) sage: msg = F((4, 8, 15, 16, 23, 42)) sage: set_random_seed(10) sage: Chan.transmit(msg) (4, 8, 4, 16, 23, 53) - >>> from sage.all import * >>> F = GF(Integer(59))**Integer(6) >>> n_err = Integer(2) >>> Chan = channels.StaticErrorRateChannel(F, n_err) >>> msg = F((Integer(4), Integer(8), Integer(15), Integer(16), Integer(23), Integer(42))) >>> set_random_seed(Integer(10)) >>> Chan.transmit(msg) (4, 8, 4, 16, 23, 53) - We can check that the input - msgis not modified:- sage: msg (4, 8, 15, 16, 23, 42) - >>> from sage.all import * >>> msg (4, 8, 15, 16, 23, 42) - If we transmit a vector which is not in the input space of - self:- sage: n_err = 2 sage: Chan = channels.StaticErrorRateChannel(GF(59)^6, n_err) sage: msg = (4, 8, 15, 16, 23, 42) sage: Chan.transmit(msg) Traceback (most recent call last): ... TypeError: Message must be an element of the input space for the given channel - >>> from sage.all import * >>> n_err = Integer(2) >>> Chan = channels.StaticErrorRateChannel(GF(Integer(59))**Integer(6), n_err) >>> msg = (Integer(4), Integer(8), Integer(15), Integer(16), Integer(23), Integer(42)) >>> Chan.transmit(msg) Traceback (most recent call last): ... TypeError: Message must be an element of the input space for the given channel - Note - One can also call directly - Chan(message), which does the same as- Chan.transmit(message)
 - transmit_unsafe(message)[source]¶
- Return - message, modified accordingly with the algorithm of the channel it was transmitted through.- This method does not check if - messagebelongs to the input space of- self.- This is an abstract method which should be reimplemented in all the subclasses of Channel. - EXAMPLES: - sage: n_err = 2 sage: Chan = channels.StaticErrorRateChannel(GF(59)^6, n_err) sage: v = Chan.input_space().random_element() sage: Chan.transmit_unsafe(v) # random (1, 33, 46, 18, 20, 49) - >>> from sage.all import * >>> n_err = Integer(2) >>> Chan = channels.StaticErrorRateChannel(GF(Integer(59))**Integer(6), n_err) >>> v = Chan.input_space().random_element() >>> Chan.transmit_unsafe(v) # random (1, 33, 46, 18, 20, 49) 
 
- class sage.coding.channel.ErrorErasureChannel(space, number_errors, number_erasures)[source]¶
- Bases: - Channel- Channel which adds errors and erases several positions in any message it transmits. - The output space of this channel is a Cartesian product between its input space and a VectorSpace of the same dimension over \(\GF{2}\). - INPUT: - space– the input and output space
- number_errors– the number of errors created in each transmitted message. It can be either an integer of a tuple. If a tuple is passed as an argument, the number of errors will be a random integer between the two bounds of this tuple.
- number_erasures– the number of erasures created in each transmitted message. It can be either an integer of a tuple. If a tuple is passed as an argument, the number of erasures will be a random integer between the two bounds of this tuple.
 - EXAMPLES: - We construct a ErrorErasureChannel which adds 2 errors and 2 erasures to any transmitted message: - sage: n_err, n_era = 2, 2 sage: Chan = channels.ErrorErasureChannel(GF(59)^40, n_err, n_era) sage: Chan Error-and-erasure channel creating 2 errors and 2 erasures of input space Vector space of dimension 40 over Finite Field of size 59 and output space The Cartesian product of (Vector space of dimension 40 over Finite Field of size 59, Vector space of dimension 40 over Finite Field of size 2) - >>> from sage.all import * >>> n_err, n_era = Integer(2), Integer(2) >>> Chan = channels.ErrorErasureChannel(GF(Integer(59))**Integer(40), n_err, n_era) >>> Chan Error-and-erasure channel creating 2 errors and 2 erasures of input space Vector space of dimension 40 over Finite Field of size 59 and output space The Cartesian product of (Vector space of dimension 40 over Finite Field of size 59, Vector space of dimension 40 over Finite Field of size 2) - We can also pass the number of errors and erasures as a couple of integers: - sage: n_err, n_era = (1, 10), (1, 10) sage: Chan = channels.ErrorErasureChannel(GF(59)^40, n_err, n_era) sage: Chan Error-and-erasure channel creating between 1 and 10 errors and between 1 and 10 erasures of input space Vector space of dimension 40 over Finite Field of size 59 and output space The Cartesian product of (Vector space of dimension 40 over Finite Field of size 59, Vector space of dimension 40 over Finite Field of size 2) - >>> from sage.all import * >>> n_err, n_era = (Integer(1), Integer(10)), (Integer(1), Integer(10)) >>> Chan = channels.ErrorErasureChannel(GF(Integer(59))**Integer(40), n_err, n_era) >>> Chan Error-and-erasure channel creating between 1 and 10 errors and between 1 and 10 erasures of input space Vector space of dimension 40 over Finite Field of size 59 and output space The Cartesian product of (Vector space of dimension 40 over Finite Field of size 59, Vector space of dimension 40 over Finite Field of size 2) - number_erasures()[source]¶
- Return the number of erasures created by - self.- EXAMPLES: - sage: n_err, n_era = 0, 3 sage: Chan = channels.ErrorErasureChannel(GF(59)^6, n_err, n_era) sage: Chan.number_erasures() (3, 3) - >>> from sage.all import * >>> n_err, n_era = Integer(0), Integer(3) >>> Chan = channels.ErrorErasureChannel(GF(Integer(59))**Integer(6), n_err, n_era) >>> Chan.number_erasures() (3, 3) 
 - number_errors()[source]¶
- Return the number of errors created by - self.- EXAMPLES: - sage: n_err, n_era = 3, 0 sage: Chan = channels.ErrorErasureChannel(GF(59)^6, n_err, n_era) sage: Chan.number_errors() (3, 3) - >>> from sage.all import * >>> n_err, n_era = Integer(3), Integer(0) >>> Chan = channels.ErrorErasureChannel(GF(Integer(59))**Integer(6), n_err, n_era) >>> Chan.number_errors() (3, 3) 
 - transmit_unsafe(message)[source]¶
- Return - messagewith as many errors as- self._number_errorsin it, and as many erasures as- self._number_erasuresin it.- If - self._number_errorswas 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. It does the same with- self._number_erasures.- All erased positions are set to 0 in the transmitted message. It is guaranteed that the erasures and the errors will never overlap: the received message will always contains exactly as many errors and erasures as expected. - This method does not check if - messagebelongs to the input space of- self.- INPUT: - message– a vector
 - OUTPUT: a couple of vectors, namely: - the transmitted message, which is - messagewith erroneous and erased positions
- the erasure vector, which contains - 1at the erased positions of the transmitted message and- 0elsewhere.
 - EXAMPLES: - sage: F = GF(59)^11 sage: n_err, n_era = 2, 2 sage: Chan = channels.ErrorErasureChannel(F, n_err, n_era) sage: msg = F((3, 14, 15, 9, 26, 53, 58, 9, 7, 9, 3)) sage: set_random_seed(10) sage: Chan.transmit_unsafe(msg) ((31, 0, 15, 9, 38, 53, 58, 9, 0, 9, 3), (0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0)) - >>> from sage.all import * >>> F = GF(Integer(59))**Integer(11) >>> n_err, n_era = Integer(2), Integer(2) >>> Chan = channels.ErrorErasureChannel(F, n_err, n_era) >>> msg = F((Integer(3), Integer(14), Integer(15), Integer(9), Integer(26), Integer(53), Integer(58), Integer(9), Integer(7), Integer(9), Integer(3))) >>> set_random_seed(Integer(10)) >>> Chan.transmit_unsafe(msg) ((31, 0, 15, 9, 38, 53, 58, 9, 0, 9, 3), (0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0)) 
 
- class sage.coding.channel.QarySymmetricChannel(space, epsilon)[source]¶
- Bases: - Channel- The \(q\)-ary symmetric, memoryless communication channel. - Given an alphabet \(\Sigma\) with \(|\Sigma| = q\) and an error probability \(\epsilon\), a \(q\)-ary symmetric channel sends an element of \(\Sigma\) into the same element with probability \(1 - \epsilon\), and any one of the other \(q - 1\) elements with probability \(\frac{\epsilon}{q - 1}\). This implementation operates over vectors in \(\Sigma^n\), and “transmits” each element of the vector independently in the above manner. - Though \(\Sigma\) is usually taken to be a finite field, this implementation allows any structure for which Sage can represent \(\Sigma^n\) and for which \(\Sigma\) has a - random_element()method. However, beware that if \(\Sigma\) is infinite, errors will not be uniformly distributed (since- random_element()does not draw uniformly at random).- The input space and the output space of this channel are the same: \(\Sigma^n\). - INPUT: - space– the input and output space of the channel; it has to be \(\GF{q}^n\) for some finite field \(\GF{q}\)
- epsilon– the transmission error probability of the individual elements
 - EXAMPLES: - We construct a - QarySymmetricChannelwhich corrupts 30% of all transmitted symbols:- sage: epsilon = 0.3 sage: Chan = channels.QarySymmetricChannel(GF(59)^50, epsilon) sage: Chan q-ary symmetric channel with error probability 0.300000000000000, of input and output space Vector space of dimension 50 over Finite Field of size 59 - >>> from sage.all import * >>> epsilon = RealNumber('0.3') >>> Chan = channels.QarySymmetricChannel(GF(Integer(59))**Integer(50), epsilon) >>> Chan q-ary symmetric channel with error probability 0.300000000000000, of input and output space Vector space of dimension 50 over Finite Field of size 59 - error_probability()[source]¶
- Return the error probability of a single symbol transmission of - self.- EXAMPLES: - sage: epsilon = 0.3 sage: Chan = channels.QarySymmetricChannel(GF(59)^50, epsilon) sage: Chan.error_probability() 0.300000000000000 - >>> from sage.all import * >>> epsilon = RealNumber('0.3') >>> Chan = channels.QarySymmetricChannel(GF(Integer(59))**Integer(50), epsilon) >>> Chan.error_probability() 0.300000000000000 
 - probability_of_at_most_t_errors(t)[source]¶
- Return the probability - selfhas to return at most- terrors.- INPUT: - t– integer
 - EXAMPLES: - sage: epsilon = 0.3 sage: Chan = channels.QarySymmetricChannel(GF(59)^50, epsilon) sage: Chan.probability_of_at_most_t_errors(20) 0.952236164579467 - >>> from sage.all import * >>> epsilon = RealNumber('0.3') >>> Chan = channels.QarySymmetricChannel(GF(Integer(59))**Integer(50), epsilon) >>> Chan.probability_of_at_most_t_errors(Integer(20)) 0.952236164579467 
 - probability_of_exactly_t_errors(t)[source]¶
- Return the probability - selfhas to return exactly- terrors.- INPUT: - t– integer
 - EXAMPLES: - sage: epsilon = 0.3 sage: Chan = channels.QarySymmetricChannel(GF(59)^50, epsilon) sage: Chan.probability_of_exactly_t_errors(15) 0.122346861835401 - >>> from sage.all import * >>> epsilon = RealNumber('0.3') >>> Chan = channels.QarySymmetricChannel(GF(Integer(59))**Integer(50), epsilon) >>> Chan.probability_of_exactly_t_errors(Integer(15)) 0.122346861835401 
 - transmit_unsafe(message)[source]¶
- Return - messagewhere each of the symbols has been changed to another from the alphabet with probability- error_probability().- This method does not check if - messagebelongs to the input space of- self.- INPUT: - message– a vector
 - EXAMPLES: - sage: F = GF(59)^11 sage: epsilon = 0.3 sage: Chan = channels.QarySymmetricChannel(F, epsilon) sage: msg = F((3, 14, 15, 9, 26, 53, 58, 9, 7, 9, 3)) sage: set_random_seed(10) sage: Chan.transmit_unsafe(msg) (3, 14, 15, 53, 12, 53, 58, 9, 55, 9, 3) - >>> from sage.all import * >>> F = GF(Integer(59))**Integer(11) >>> epsilon = RealNumber('0.3') >>> Chan = channels.QarySymmetricChannel(F, epsilon) >>> msg = F((Integer(3), Integer(14), Integer(15), Integer(9), Integer(26), Integer(53), Integer(58), Integer(9), Integer(7), Integer(9), Integer(3))) >>> set_random_seed(Integer(10)) >>> Chan.transmit_unsafe(msg) (3, 14, 15, 53, 12, 53, 58, 9, 55, 9, 3) 
 
- class sage.coding.channel.StaticErrorRateChannel(space, number_errors)[source]¶
- Bases: - Channel- Channel which adds a static number of errors 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
- number_errors– the number of errors added to each transmitted message It can be either an integer of a tuple. If a tuple is passed as argument, the number of errors will be a random integer between the two bounds of the tuple.
 - EXAMPLES: - We construct a - StaticErrorRateChannelwhich adds 2 errors to any transmitted message:- sage: n_err = 2 sage: Chan = channels.StaticErrorRateChannel(GF(59)^40, n_err) sage: Chan Static error rate channel creating 2 errors, of input and output space Vector space of dimension 40 over Finite Field of size 59 - >>> from sage.all import * >>> n_err = Integer(2) >>> Chan = channels.StaticErrorRateChannel(GF(Integer(59))**Integer(40), n_err) >>> Chan Static error rate channel creating 2 errors, 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.StaticErrorRateChannel(GF(59)^40, n_err) sage: Chan Static error rate channel creating between 1 and 10 errors, of input and output space Vector space of dimension 40 over Finite Field of size 59 - >>> from sage.all import * >>> n_err = (Integer(1), Integer(10)) >>> Chan = channels.StaticErrorRateChannel(GF(Integer(59))**Integer(40), n_err) >>> Chan Static error rate channel creating between 1 and 10 errors, of input and output space Vector space of dimension 40 over Finite Field of size 59 - number_errors()[source]¶
- Return the number of errors created by - self.- EXAMPLES: - sage: n_err = 3 sage: Chan = channels.StaticErrorRateChannel(GF(59)^6, n_err) sage: Chan.number_errors() (3, 3) - >>> from sage.all import * >>> n_err = Integer(3) >>> Chan = channels.StaticErrorRateChannel(GF(Integer(59))**Integer(6), n_err) >>> Chan.number_errors() (3, 3) 
 - transmit_unsafe(message)[source]¶
- Return - messagewith as many errors as- self._number_errorsin it.- If - self._number_errorswas 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 - messagebelongs to the input space of- self.- INPUT: - message– a vector
 - OUTPUT: a vector of the output space - EXAMPLES: - sage: F = GF(59)^6 sage: n_err = 2 sage: Chan = channels.StaticErrorRateChannel(F, n_err) sage: msg = F((4, 8, 15, 16, 23, 42)) sage: set_random_seed(10) sage: Chan.transmit_unsafe(msg) (4, 8, 4, 16, 23, 53) - >>> from sage.all import * >>> F = GF(Integer(59))**Integer(6) >>> n_err = Integer(2) >>> Chan = channels.StaticErrorRateChannel(F, n_err) >>> msg = F((Integer(4), Integer(8), Integer(15), Integer(16), Integer(23), Integer(42))) >>> set_random_seed(Integer(10)) >>> Chan.transmit_unsafe(msg) (4, 8, 4, 16, 23, 53) - This checks that Issue #19863 is fixed: - sage: V = VectorSpace(GF(2), 1000) sage: Chan = channels.StaticErrorRateChannel(V, 367) sage: c = V.random_element() sage: (c - Chan(c)).hamming_weight() 367 - >>> from sage.all import * >>> V = VectorSpace(GF(Integer(2)), Integer(1000)) >>> Chan = channels.StaticErrorRateChannel(V, Integer(367)) >>> c = V.random_element() >>> (c - Chan(c)).hamming_weight() 367 
 
- sage.coding.channel.format_interval(t)[source]¶
- Return a formatted string representation of - t.- This method should be called by any representation function in Channel classes. - Note - This is a helper function, which should only be used when implementing new channels. - INPUT: - t– list or a tuple
 - OUTPUT: string 
- sage.coding.channel.random_error_vector(n, F, error_positions)[source]¶
- Return a vector of length - nover- Ffilled with random nonzero coefficients at the positions given by- error_positions.- Note - This is a helper function, which should only be used when implementing new channels. - INPUT: - n– the length of the vector
- F– the field over which the vector is defined
- error_positions– the nonzero positions of the vector
 - OUTPUT: a vector of - F- AUTHORS: - This function is taken from codinglib (https://bitbucket.org/jsrn/codinglib/) and was written by Johan Nielsen. - EXAMPLES: - sage: from sage.coding.channel import random_error_vector sage: random_error_vector(5, GF(2), [1,3]) (0, 1, 0, 1, 0) - >>> from sage.all import * >>> from sage.coding.channel import random_error_vector >>> random_error_vector(Integer(5), GF(Integer(2)), [Integer(1),Integer(3)]) (0, 1, 0, 1, 0)