Skip to content
This repository was archived by the owner on Jan 30, 2023. It is now read-only.

Commit 64ee227

Browse files
committed
Merged ticket #21328 in
2 parents 8409076 + 1aa4b4e commit 64ee227

File tree

5 files changed

+358
-2
lines changed

5 files changed

+358
-2
lines changed

src/doc/en/reference/coding/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ Linear codes and related constructions
4141
sage/coding/guava
4242
sage/coding/binary_code
4343
sage/coding/reed_muller_code
44+
sage/coding/parity_check_code
4445

4546
Bounds on codes
4647
---------------

src/sage/coding/codes_catalog.py

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
from .reed_muller_code import ReedMullerCode, BinaryReedMullerCode
4040
from .extended_code import ExtendedCode
4141
from .subfield_subcode import SubfieldSubcode
42+
from .parity_check_code import ParityCheckCode
4243

4344
from .guava import QuasiQuadraticResidueCode, RandomLinearCodeGuava
4445
_lazy_import('sage.coding.punctured_code', 'PuncturedCode')

src/sage/coding/encoders_catalog.py

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#*****************************************************************************
3737
# Copyright (C) 2009 David Joyner <[email protected]>
3838
# 2015 David Lucas <[email protected]>
39+
# 2016 Tania Richmond <[email protected]>
3940
#
4041
# Distributed under the terms of the GNU General Public License (GPL),
4142
# version 2 or later (at your preference).
@@ -54,3 +55,4 @@
5455
_lazy_import('sage.coding.extended_code', 'ExtendedCodeExtendedMatrixEncoder')
5556
_lazy_import('sage.coding.punctured_code', 'PuncturedCodePuncturedMatrixEncoder')
5657
_lazy_import('sage.coding.subfield_subcode', 'SubfieldSubcodeParityCheckEncoder')
58+
_lazy_import('sage.coding.parity_check_code', ['ParityCheckCodeGeneratorMatrixEncoder','ParityCheckCodeStraightforwardEncoder'])

src/sage/coding/linear_code.py

-2
Original file line numberDiff line numberDiff line change
@@ -2772,7 +2772,6 @@ def relative_distance(self):
27722772
"""
27732773
return self.minimum_distance() / self.length()
27742774

2775-
27762775
def rate(self):
27772776
r"""
27782777
Return the ratio of the number of information symbols to
@@ -2786,7 +2785,6 @@ def rate(self):
27862785
"""
27872786
return self.dimension() / self.length()
27882787

2789-
27902788
def redundancy_matrix(self):
27912789
r"""
27922790
Returns the non-identity columns of a systematic generator matrix for

src/sage/coding/parity_check_code.py

+354
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
r"""
2+
Parity-check code
3+
4+
A simple way of detecting up to one error is to use the device of adding a
5+
parity check to ensure that the sum of the digits in a transmitted word is
6+
even.
7+
8+
A parity-check code of dimension `k` over `F_q` is the set:
9+
`\{(m_1, m_2, \dots, m_k, - \Sigma_{i=1}^k m_i) \mid (m_1, m_2, \dots, m_k) \in F_q^k\}`
10+
11+
REFERENCE:
12+
13+
.. [W88] Codes and Cryptography, Dominic Welsh, Oxford Sciences
14+
Publications, 1988
15+
"""
16+
17+
# *****************************************************************************
18+
# Copyright (C) 2016 Tania Richmond <[email protected]>
19+
#
20+
# This program is free software: you can redistribute it and/or modify
21+
# it under the terms of the GNU General Public License as published by
22+
# the Free Software Foundation, either version 2 of the License, or
23+
# (at your option) any later version.
24+
# http://www.gnu.org/licenses/
25+
# *****************************************************************************
26+
27+
from sage.coding.linear_code import AbstractLinearCode,\
28+
LinearCodeGeneratorMatrixEncoder
29+
from sage.coding.encoder import Encoder
30+
from sage.rings.integer import Integer
31+
from sage.rings.finite_rings.finite_field_constructor import GF
32+
from sage.matrix.constructor import identity_matrix
33+
from sage.modules.free_module_element import vector
34+
from sage.modules.free_module import VectorSpace
35+
36+
37+
class ParityCheckCode(AbstractLinearCode):
38+
r"""
39+
Representation of a parity-check code.
40+
41+
INPUT:
42+
43+
- ``base_field`` -- the base field over which ``self`` is defined.
44+
45+
- ``dimension`` -- the dimension of ``self``.
46+
47+
EXAMPLES::
48+
49+
sage: C = codes.ParityCheckCode(GF(5), 7)
50+
sage: C
51+
[8, 7] parity-check code over GF(5)
52+
"""
53+
54+
_registered_encoders = {}
55+
_registered_decoders = {}
56+
57+
def __init__(self, base_field=GF(2), dimension=7):
58+
r"""
59+
Initialize mandatory parameters for a parity-check code object.
60+
61+
INPUT:
62+
63+
- ``base_field`` -- the base field over which ``self`` is defined
64+
or GF(2) if no base_field.
65+
66+
- ``dimension`` -- the dimension of ``self`` or 7 if no dimension.
67+
68+
EXAMPLES::
69+
70+
sage: C = codes.ParityCheckCode(GF(5), 7)
71+
sage: C
72+
[8, 7] parity-check code over GF(5)
73+
"""
74+
75+
if not base_field.is_finite():
76+
raise ValueError("base_field has to be a finite field")
77+
if not isinstance(dimension, (Integer, int)):
78+
raise ValueError("dimension must be an integer")
79+
80+
self._dimension = dimension
81+
super(ParityCheckCode, self).__init__(
82+
base_field, dimension + 1, "ParityCheckCodeGeneratorMatrixEncoder",
83+
"Syndrome")
84+
85+
def __eq__(self, other):
86+
r"""
87+
Test equality of parity-check code objects.
88+
89+
EXAMPLES::
90+
91+
sage: C1 = codes.ParityCheckCode(GF(5), 7)
92+
sage: C2 = codes.ParityCheckCode(GF(5), 7)
93+
sage: C1 == C2
94+
True
95+
"""
96+
return (isinstance(other, ParityCheckCode)
97+
and self.base_field() == other.base_field()
98+
and self.dimension() == other.dimension())
99+
100+
def _repr_(self):
101+
r"""
102+
Return a string representation of ``self``.
103+
104+
EXAMPLES::
105+
106+
sage: C = codes.ParityCheckCode(GF(5), 7)
107+
sage: C
108+
[8, 7] parity-check code over GF(5)
109+
"""
110+
return ("[%s, %s] parity-check code over GF(%s)"
111+
% (self.length(), self.dimension(),
112+
self.base_field().cardinality()))
113+
114+
def _latex_(self):
115+
r"""
116+
Return a latex representation of ``self``.
117+
118+
EXAMPLES::
119+
120+
sage: C = codes.ParityCheckCode(GF(5), 7)
121+
sage: latex(C)
122+
[8, 7] \textnormal{parity-check code over } \Bold{F}_{5}
123+
"""
124+
return "[%s, %s] \\textnormal{parity-check code over } %s"\
125+
% (self.length(), self.dimension(), self.base_field()._latex_())
126+
127+
def minimum_distance(self):
128+
r"""
129+
Return the minimum distance of ``self``.
130+
131+
It is always 2 as ``self`` is a parity-check code.
132+
133+
EXAMPLES::
134+
135+
sage: C = codes.ParityCheckCode(GF(5), 7)
136+
sage: C.minimum_distance()
137+
2
138+
"""
139+
return 2
140+
141+
142+
####################### encoders ###############################
143+
144+
class ParityCheckCodeGeneratorMatrixEncoder(LinearCodeGeneratorMatrixEncoder):
145+
r"""
146+
Encoder for parity-check codes which uses a generator matrix to obtain
147+
codewords.
148+
149+
INPUT:
150+
151+
- ``code`` -- the associated code of this encoder.
152+
153+
EXAMPLES::
154+
155+
sage: C = codes.ParityCheckCode(GF(5), 7)
156+
sage: E = codes.encoders.ParityCheckCodeGeneratorMatrixEncoder(C)
157+
sage: E
158+
Generator matrix-based encoder for [8, 7] parity-check code over GF(5)
159+
160+
Actually, we can construct the encoder from ``C`` directly::
161+
162+
sage: E = C.encoder("ParityCheckCodeGeneratorMatrixEncoder")
163+
sage: E
164+
Generator matrix-based encoder for [8, 7] parity-check code over GF(5)
165+
"""
166+
167+
def __init__(self, code):
168+
r"""
169+
TESTS:
170+
171+
If ``code`` is not a parity-check code, an error is raised::
172+
173+
sage: C = codes.random_linear_code(GF(11), 10, 4)
174+
sage: codes.encoders.ParityCheckCodeGeneratorMatrixEncoder(C)
175+
Traceback (most recent call last):
176+
...
177+
ValueError: code has to be a parity-check code
178+
"""
179+
if not isinstance(code, ParityCheckCode):
180+
raise ValueError("code has to be a parity-check code")
181+
super(ParityCheckCodeGeneratorMatrixEncoder, self).__init__(code)
182+
183+
def generator_matrix(self):
184+
r"""
185+
Return a generator matrix of ``self``.
186+
187+
EXAMPLES::
188+
189+
sage: C = codes.ParityCheckCode(GF(5),7)
190+
sage: E = codes.encoders.ParityCheckCodeGeneratorMatrixEncoder(C)
191+
sage: E.generator_matrix()
192+
[1 0 0 0 0 0 0 4]
193+
[0 1 0 0 0 0 0 4]
194+
[0 0 1 0 0 0 0 4]
195+
[0 0 0 1 0 0 0 4]
196+
[0 0 0 0 1 0 0 4]
197+
[0 0 0 0 0 1 0 4]
198+
[0 0 0 0 0 0 1 4]
199+
"""
200+
k = self.code().dimension()
201+
field = self.code().base_field()
202+
G = identity_matrix(field, k)
203+
G = G.augment(vector(field, [-field.one()] * k))
204+
return G
205+
206+
207+
class ParityCheckCodeStraightforwardEncoder(Encoder):
208+
r"""
209+
Encoder for parity-check codes which computes the sum of message symbols
210+
and appends its opposite to the message to obtain codewords.
211+
212+
INPUT:
213+
214+
- ``code`` -- the associated code of this encoder.
215+
216+
EXAMPLES::
217+
218+
sage: C = codes.ParityCheckCode(GF(5), 7)
219+
sage: E = codes.encoders.ParityCheckCodeStraightforwardEncoder(C)
220+
sage: E
221+
Parity-check encoder for the [8, 7] parity-check code over GF(5)
222+
223+
Actually, we can construct the encoder from ``C`` directly::
224+
225+
sage: E = C.encoder("ParityCheckCodeStraightforwardEncoder")
226+
sage: E
227+
Parity-check encoder for the [8, 7] parity-check code over GF(5)
228+
"""
229+
230+
def __init__(self, code):
231+
r"""
232+
TESTS:
233+
234+
If ``code`` is not a parity-check code, an error is raised::
235+
236+
sage: C = codes.random_linear_code(GF(11), 10, 4)
237+
sage: codes.encoders.ParityCheckCodeStraightforwardEncoder(C)
238+
Traceback (most recent call last):
239+
...
240+
ValueError: code has to be a parity-check code
241+
"""
242+
if not isinstance(code, ParityCheckCode):
243+
raise ValueError("code has to be a parity-check code")
244+
super(ParityCheckCodeStraightforwardEncoder, self).__init__(code)
245+
246+
def _repr_(self):
247+
r"""
248+
Return a string representation of ``self``.
249+
250+
EXAMPLES::
251+
252+
sage: C = codes.ParityCheckCode(GF(5), 7)
253+
sage: codes.encoders.ParityCheckCodeStraightforwardEncoder(C)
254+
Parity-check encoder for the [8, 7] parity-check code over GF(5)
255+
"""
256+
return "Parity-check encoder for the %s" % self.code()
257+
258+
def _latex_(self):
259+
r"""
260+
Return a latex representation of ``self``.
261+
262+
EXAMPLES::
263+
264+
sage: C = codes.ParityCheckCode(GF(5), 7)
265+
sage: E = codes.encoders.ParityCheckCodeStraightforwardEncoder(C)
266+
sage: latex(E)
267+
\textnormal{Parity-check encoder for the } [8, 7] \textnormal{parity-check code over } \Bold{F}_{5}
268+
"""
269+
return ("\\textnormal{Parity-check encoder for the } %s" %
270+
self.code()._latex_())
271+
272+
def __eq__(self, other):
273+
r"""
274+
Test equality of parity-check code objects.
275+
276+
EXAMPLES::
277+
278+
sage: C1 = codes.ParityCheckCode(GF(5), 7)
279+
sage: C2 = codes.ParityCheckCode(GF(5), 7)
280+
sage: C1 == C2
281+
True
282+
"""
283+
return (isinstance(other, ParityCheckCodeStraightforwardEncoder)
284+
and self.code() == other.code())
285+
286+
def encode(self, message):
287+
r"""
288+
Transform the vector ``message`` into a codeword of :meth:`code`.
289+
290+
INPUT:
291+
292+
- ``message`` -- A ``self.code().dimension()``-vector from the message
293+
space of ``self``.
294+
295+
OUTPUT:
296+
297+
- A codeword in associated code of ``self``.
298+
299+
EXAMPLES::
300+
301+
sage: C = codes.ParityCheckCode(GF(5),7)
302+
sage: message = vector(C.base_field(),[1,0,4,2,0,3,2])
303+
sage: C.encode(message)
304+
(1, 0, 4, 2, 0, 3, 2, 3)
305+
"""
306+
parity=self.code().base_field().zero()
307+
for i in message.list():
308+
parity += i
309+
return vector(self.code().base_field(), message.list() + [-parity])
310+
311+
def unencode_nocheck(self, word):
312+
r"""
313+
Return the message corresponding to the vector ``word``.
314+
315+
Use this method with caution: it does not check if ``word``
316+
belongs to the code.
317+
318+
INPUT:
319+
320+
- ``word`` -- A ``self.code().length()``-vector from the ambiant space
321+
of ``self``.
322+
323+
OUTPUT:
324+
325+
- A vector corresponding to the ``self.code().dimension()``-first
326+
symbols in ``word``.
327+
328+
EXAMPLES::
329+
330+
sage: C = codes.ParityCheckCode(GF(5), 7)
331+
sage: word = vector(C.base_field(), [1, 0, 4, 2, 0, 3, 2, 3])
332+
sage: E = codes.encoders.ParityCheckCodeStraightforwardEncoder(C)
333+
sage: E.unencode_nocheck(word)
334+
(1, 0, 4, 2, 0, 3, 2)
335+
"""
336+
return word[:-1]
337+
338+
def message_space(self):
339+
r"""
340+
Return the message space of ``self``.
341+
342+
EXAMPLES::
343+
344+
sage: C = codes.ParityCheckCode(GF(5),7)
345+
sage: E = codes.encoders.ParityCheckCodeStraightforwardEncoder(C)
346+
sage: E.message_space()
347+
Vector space of dimension 7 over Finite Field of size 5
348+
"""
349+
return VectorSpace(self.code().base_field(), self.code().dimension())
350+
351+
####################### registration ###############################
352+
353+
ParityCheckCode._registered_encoders["ParityCheckCodeGeneratorMatrixEncoder"] = ParityCheckCodeGeneratorMatrixEncoder
354+
ParityCheckCode._registered_encoders["ParityCheckCodeStraightforwardEncoder"] = ParityCheckCodeStraightforwardEncoder

0 commit comments

Comments
 (0)