Skip to content

Commit 5669cf0

Browse files
Release Managervbraun
Release Manager
authored andcommitted
Trac #19930: A proper class for Hamming codes
`codes.HammingCode` is not a constructor for a class, but a method which builds a generic linear code. This ticket proposes a class implementation of Hamming codes, using the API introduced in #18099 which properly sets Hamming codes as a class. It also comes with a new generic encoder for codes built from a parity check matrix. URL: http://trac.sagemath.org/19930 Reported by: dlucas Ticket author(s): David Lucas Reviewer(s): Clément Pernet
2 parents 3543ce0 + 2b6875a commit 5669cf0

File tree

11 files changed

+398
-212
lines changed

11 files changed

+398
-212
lines changed

src/doc/en/constructions/linear_codes.rst

+8-8
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ Sage can compute Hamming codes
2222

2323
::
2424

25-
sage: C = codes.HammingCode(3,GF(3))
25+
sage: C = codes.HammingCode(GF(3), 3)
2626
sage: C
27-
Linear code of length 13, dimension 10 over Finite Field of size 3
27+
[13, 10] Hamming Code over Finite Field of size 3
2828
sage: C.minimum_distance()
2929
3
3030
sage: C.generator_matrix()
@@ -74,10 +74,10 @@ a check matrix, and the dual code:
7474

7575
::
7676

77-
sage: C = codes.HammingCode(3,GF(2))
77+
sage: C = codes.HammingCode(GF(2), 3)
7878
sage: Cperp = C.dual_code()
7979
sage: C; Cperp
80-
Linear code of length 7, dimension 4 over Finite Field of size 2
80+
[7, 4] Hamming Code over Finite Field of size 2
8181
Linear code of length 7, dimension 3 over Finite Field of size 2
8282
sage: C.generator_matrix()
8383
[1 0 0 0 0 1 1]
@@ -90,7 +90,7 @@ a check matrix, and the dual code:
9090
[0 0 0 1 1 1 1]
9191
sage: C.dual_code()
9292
Linear code of length 7, dimension 3 over Finite Field of size 2
93-
sage: C = codes.HammingCode(3,GF(4,'a'))
93+
sage: C = codes.HammingCode(GF(4,'a'), 3)
9494
sage: C.dual_code()
9595
Linear code of length 21, dimension 3 over Finite Field in a of size 2^2
9696

@@ -102,7 +102,7 @@ implemented.
102102

103103
::
104104

105-
sage: C = codes.HammingCode(3,GF(2))
105+
sage: C = codes.HammingCode(GF(2), 3)
106106
sage: MS = MatrixSpace(GF(2),1,7)
107107
sage: F = GF(2); a = F.gen()
108108
sage: v = vector([a,a,F(0),a,a,F(0),a])
@@ -116,9 +116,9 @@ can use the matplotlib package included with Sage:
116116

117117
::
118118

119-
sage: C = codes.HammingCode(4,GF(2))
119+
sage: C = codes.HammingCode(GF(2), 4)
120120
sage: C
121-
Linear code of length 15, dimension 11 over Finite Field of size 2
121+
[15, 11] Hamming Code over Finite Field of size 2
122122
sage: w = C.weight_distribution(); w
123123
[1, 0, 0, 35, 105, 168, 280, 435, 435, 280, 168, 105, 35, 0, 0, 1]
124124
sage: J = range(len(w))

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

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ Linear codes and related constructions
2626

2727
sage/coding/binary_code
2828
sage/coding/grs
29+
sage/coding/hamming_code
2930
sage/coding/guruswami_sudan/gs_decoder
3031
sage/coding/guruswami_sudan/interpolation
3132
sage/coding/guruswami_sudan/rootfinding

src/sage/coding/binary_code.pyx

+2-2
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ cdef class BinaryCode:
861861
"""
862862
cdef int i, j
863863
from sage.matrix.constructor import matrix
864-
from sage.rings.all import GF
864+
from sage.rings.finite_rings.finite_field_constructor import GF
865865
rows = []
866866
for i from 0 <= i < self.nrows:
867867
row = [0]*self.ncols
@@ -4226,7 +4226,7 @@ cdef class BinaryCodeClassifier:
42264226
break
42274227
if bingo2:
42284228
from sage.matrix.constructor import Matrix
4229-
from sage.rings.all import GF
4229+
from sage.rings.finite_rings.finite_field_constructor import GF
42304230
M = Matrix(GF(2), B_aug.nrows, B_aug.ncols)
42314231
for i from 0 <= i < B_aug.ncols:
42324232
for j from 0 <= j < B_aug.nrows:

src/sage/coding/code_constructions.py

+11-53
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
88
All codes available here can be accessed through the ``codes`` object::
99
10-
sage: codes.HammingCode(3,GF(2))
11-
Linear code of length 7, dimension 4 over Finite Field of size 2
10+
sage: codes.HammingCode(GF(2), 3)
11+
[7, 4] Hamming Code over Finite Field of size 2
12+
1213
1314
Let `F` be a finite field with `q` elements.
1415
Here's a constructive definition of a cyclic code of length
@@ -907,53 +908,6 @@ def ExtendedTernaryGolayCode():
907908
# C = TernaryGolayCode()
908909
# return C.extended_code()
909910

910-
def HammingCode(r,F):
911-
r"""
912-
Implements the Hamming codes.
913-
914-
The `r^{th}` Hamming code over `F=GF(q)` is an
915-
`[n,k,d]` code with length `n=(q^r-1)/(q-1)`,
916-
dimension `k=(q^r-1)/(q-1) - r` and minimum distance
917-
`d=3`. The parity check matrix of a Hamming code has rows
918-
consisting of all nonzero vectors of length r in its columns,
919-
modulo a scalar factor so no parallel columns arise. A Hamming code
920-
is a single error-correcting code.
921-
922-
INPUT:
923-
924-
925-
- ``r`` - an integer 2
926-
927-
- ``F`` - a finite field.
928-
929-
930-
OUTPUT: Returns the r-th q-ary Hamming code.
931-
932-
EXAMPLES::
933-
934-
sage: codes.HammingCode(3,GF(2))
935-
Linear code of length 7, dimension 4 over Finite Field of size 2
936-
sage: C = codes.HammingCode(3,GF(3)); C
937-
Linear code of length 13, dimension 10 over Finite Field of size 3
938-
sage: C.minimum_distance()
939-
3
940-
sage: C.minimum_distance(algorithm='gap') # long time, check d=3
941-
3
942-
sage: C = codes.HammingCode(3,GF(4,'a')); C
943-
Linear code of length 21, dimension 18 over Finite Field in a of size 2^2
944-
"""
945-
q = F.order()
946-
n = (q**r-1)/(q-1)
947-
k = n-r
948-
MS = MatrixSpace(F,n,r)
949-
X = ProjectiveSpace(r-1,F)
950-
PFn = [list(p) for p in X.point_set(F).points(F)]
951-
H = MS(PFn).transpose()
952-
Cd = LinearCode(H)
953-
# Hamming code always has distance 3, so we provide the distance.
954-
return LinearCode(Cd.dual_code().generator_matrix(), d=3)
955-
956-
957911
def LinearCodeFromCheckMatrix(H):
958912
r"""
959913
A linear [n,k]-code C is uniquely determined by its generator
@@ -975,18 +929,22 @@ def LinearCodeFromCheckMatrix(H):
975929
976930
EXAMPLES::
977931
978-
sage: C = codes.HammingCode(3,GF(2))
932+
sage: C = codes.HammingCode(GF(2), 3)
979933
sage: H = C.parity_check_matrix(); H
980934
[1 0 1 0 1 0 1]
981935
[0 1 1 0 0 1 1]
982936
[0 0 0 1 1 1 1]
983-
sage: codes.LinearCodeFromCheckMatrix(H) == C
937+
sage: Gh = codes.LinearCodeFromCheckMatrix(H).generator_matrix()
938+
sage: Gc = C.generator_matrix_systematic()
939+
sage: Gh == Gc
984940
True
985-
sage: C = codes.HammingCode(2,GF(3))
941+
sage: C = codes.HammingCode(GF(3), 2)
986942
sage: H = C.parity_check_matrix(); H
987943
[1 0 1 1]
988944
[0 1 1 2]
989-
sage: codes.LinearCodeFromCheckMatrix(H) == C
945+
sage: Gh = codes.LinearCodeFromCheckMatrix(H).generator_matrix()
946+
sage: Gc = C.generator_matrix_systematic()
947+
sage: Gh == Gc
990948
True
991949
sage: C = codes.RandomLinearCode(10,5,GF(4,"a"))
992950
sage: H = C.parity_check_matrix()

src/sage/coding/codecan/autgroup_can_label.pyx

+13-13
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ REFERENCES:
4747
EXAMPLES::
4848
4949
sage: from sage.coding.codecan.autgroup_can_label import LinearCodeAutGroupCanLabel
50-
sage: C = codes.HammingCode(3, GF(3)).dual_code()
50+
sage: C = codes.HammingCode(GF(3), 3).dual_code()
5151
sage: P = LinearCodeAutGroupCanLabel(C)
5252
sage: P.get_canonical_form().generator_matrix()
5353
[1 0 0 0 0 1 1 1 1 1 1 1 1]
@@ -63,7 +63,7 @@ EXAMPLES::
6363
6464
If the dimension of the dual code is smaller, we will work on this code::
6565
66-
sage: C2 = codes.HammingCode(3, GF(3))
66+
sage: C2 = codes.HammingCode(GF(3), 3)
6767
sage: P2 = LinearCodeAutGroupCanLabel(C2)
6868
sage: P2.get_canonical_form().parity_check_matrix() == P.get_canonical_form().generator_matrix()
6969
True
@@ -72,7 +72,7 @@ There is a specialization of this algorithm to pass a coloring on the
7272
coordinates. This is just a list of lists, telling the algorithm which
7373
columns do share the same coloring::
7474
75-
sage: C = codes.HammingCode(3, GF(4, 'a')).dual_code()
75+
sage: C = codes.HammingCode(GF(4, 'a'), 3).dual_code()
7676
sage: P = LinearCodeAutGroupCanLabel(C, P=[ [0], [1], range(2, C.length()) ])
7777
sage: P.get_autom_order()
7878
864
@@ -169,7 +169,7 @@ class LinearCodeAutGroupCanLabel:
169169
EXAMPLES::
170170
171171
sage: from sage.coding.codecan.autgroup_can_label import LinearCodeAutGroupCanLabel
172-
sage: C = codes.HammingCode(3, GF(3)).dual_code()
172+
sage: C = codes.HammingCode(GF(3), 3).dual_code()
173173
sage: P = LinearCodeAutGroupCanLabel(C)
174174
sage: P.get_canonical_form().generator_matrix()
175175
[1 0 0 0 0 1 1 1 1 1 1 1 1]
@@ -206,7 +206,7 @@ class LinearCodeAutGroupCanLabel:
206206
EXAMPLES::
207207
208208
sage: from sage.coding.codecan.autgroup_can_label import LinearCodeAutGroupCanLabel
209-
sage: C = codes.HammingCode(3, GF(2)).dual_code()
209+
sage: C = codes.HammingCode(GF(2), 3).dual_code()
210210
sage: P = LinearCodeAutGroupCanLabel(C)
211211
sage: P.get_canonical_form().generator_matrix()
212212
[1 0 0 0 1 1 1]
@@ -220,9 +220,9 @@ class LinearCodeAutGroupCanLabel:
220220
[0 0 1 0 1 1 1]
221221
"""
222222
from sage.groups.semimonomial_transformations.semimonomial_transformation_group import SemimonomialTransformationGroup
223-
from sage.coding.linear_code import LinearCode
223+
from sage.coding.linear_code import LinearCode, AbstractLinearCode
224224

225-
if not isinstance(C, LinearCode):
225+
if not isinstance(C, AbstractLinearCode):
226226
raise TypeError("%s is not a linear code"%C)
227227

228228
self.C = C
@@ -531,7 +531,7 @@ class LinearCodeAutGroupCanLabel:
531531
EXAMPLES::
532532
533533
sage: from sage.coding.codecan.autgroup_can_label import LinearCodeAutGroupCanLabel
534-
sage: C = codes.HammingCode(3, GF(3)).dual_code()
534+
sage: C = codes.HammingCode(GF(3), 3).dual_code()
535535
sage: CF1 = LinearCodeAutGroupCanLabel(C).get_canonical_form()
536536
sage: s = SemimonomialTransformationGroup(GF(3), C.length()).an_element()
537537
sage: C2 = LinearCode(s*C.generator_matrix())
@@ -548,7 +548,7 @@ class LinearCodeAutGroupCanLabel:
548548
EXAMPLES::
549549
550550
sage: from sage.coding.codecan.autgroup_can_label import LinearCodeAutGroupCanLabel
551-
sage: C = codes.HammingCode(3, GF(2)).dual_code()
551+
sage: C = codes.HammingCode(GF(2), 3).dual_code()
552552
sage: P = LinearCodeAutGroupCanLabel(C)
553553
sage: g = P.get_transporter()
554554
sage: D = P.get_canonical_form()
@@ -564,7 +564,7 @@ class LinearCodeAutGroupCanLabel:
564564
EXAMPLES::
565565
566566
sage: from sage.coding.codecan.autgroup_can_label import LinearCodeAutGroupCanLabel
567-
sage: C = codes.HammingCode(3, GF(2)).dual_code()
567+
sage: C = codes.HammingCode(GF(2), 3).dual_code()
568568
sage: A = LinearCodeAutGroupCanLabel(C).get_autom_gens()
569569
sage: Gamma = C.generator_matrix().echelon_form()
570570
sage: all([(g*Gamma).echelon_form() == Gamma for g in A])
@@ -579,7 +579,7 @@ class LinearCodeAutGroupCanLabel:
579579
EXAMPLES::
580580
581581
sage: from sage.coding.codecan.autgroup_can_label import LinearCodeAutGroupCanLabel
582-
sage: C = codes.HammingCode(3, GF(2)).dual_code()
582+
sage: C = codes.HammingCode(GF(2), 3).dual_code()
583583
sage: LinearCodeAutGroupCanLabel(C).get_autom_order()
584584
168
585585
"""
@@ -599,7 +599,7 @@ class LinearCodeAutGroupCanLabel:
599599
EXAMPLES::
600600
601601
sage: from sage.coding.codecan.autgroup_can_label import LinearCodeAutGroupCanLabel
602-
sage: C = codes.HammingCode(3, GF(4, 'a')).dual_code()
602+
sage: C = codes.HammingCode(GF(4, 'a'), 3).dual_code()
603603
sage: A = LinearCodeAutGroupCanLabel(C).get_PGammaL_gens()
604604
sage: Gamma = C.generator_matrix()
605605
sage: N = [ x.monic() for x in Gamma.columns() ]
@@ -628,7 +628,7 @@ class LinearCodeAutGroupCanLabel:
628628
EXAMPLES::
629629
630630
sage: from sage.coding.codecan.autgroup_can_label import LinearCodeAutGroupCanLabel
631-
sage: C = codes.HammingCode(3, GF(4, 'a')).dual_code()
631+
sage: C = codes.HammingCode(GF(4, 'a'), 3).dual_code()
632632
sage: LinearCodeAutGroupCanLabel(C).get_PGammaL_order() == GL(3, GF(4, 'a')).order()*2/3
633633
True
634634
"""

src/sage/coding/codecan/codecan.pyx

+10-10
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ EXAMPLES:
6060
Get the canonical form of the Simplex code::
6161
6262
sage: from sage.coding.codecan.codecan import PartitionRefinementLinearCode
63-
sage: mat = codes.HammingCode(3, GF(3)).dual_code().generator_matrix()
63+
sage: mat = codes.HammingCode(GF(3), 3).dual_code().generator_matrix()
6464
sage: P = PartitionRefinementLinearCode(mat.ncols(), mat)
6565
sage: cf = P.get_canonical_form(); cf
6666
[1 0 0 0 0 1 1 1 1 1 1 1 1]
@@ -466,7 +466,7 @@ cdef class PartitionRefinementLinearCode(PartitionRefinement_generic):
466466
EXAMPLES::
467467
468468
sage: from sage.coding.codecan.codecan import PartitionRefinementLinearCode
469-
sage: mat = codes.HammingCode(3, GF(3)).dual_code().generator_matrix()
469+
sage: mat = codes.HammingCode(GF(3), 3).dual_code().generator_matrix()
470470
sage: P = PartitionRefinementLinearCode(mat.ncols(), mat)
471471
sage: cf = P.get_canonical_form(); cf
472472
[1 0 0 0 0 1 1 1 1 1 1 1 1]
@@ -493,7 +493,7 @@ cdef class PartitionRefinementLinearCode(PartitionRefinement_generic):
493493
EXAMPLES::
494494
495495
sage: from sage.coding.codecan.codecan import PartitionRefinementLinearCode
496-
sage: mat = codes.HammingCode(3, GF(3)).dual_code().generator_matrix()
496+
sage: mat = codes.HammingCode(GF(3), 3).dual_code().generator_matrix()
497497
sage: P = PartitionRefinementLinearCode(mat.ncols(), mat)
498498
"""
499499
self._k = generator_matrix.nrows()
@@ -533,7 +533,7 @@ cdef class PartitionRefinementLinearCode(PartitionRefinement_generic):
533533
EXAMPLES::
534534
535535
sage: from sage.coding.codecan.codecan import PartitionRefinementLinearCode
536-
sage: mat = codes.HammingCode(3, GF(3)).dual_code().generator_matrix()
536+
sage: mat = codes.HammingCode(GF(3), 3).dual_code().generator_matrix()
537537
sage: P = PartitionRefinementLinearCode(mat.ncols(), mat)
538538
"""
539539
self._run(P, algorithm_type)
@@ -559,7 +559,7 @@ cdef class PartitionRefinementLinearCode(PartitionRefinement_generic):
559559
EXAMPLES::
560560
561561
sage: from sage.coding.codecan.codecan import PartitionRefinementLinearCode
562-
sage: mat = codes.HammingCode(3, GF(3)).dual_code().generator_matrix()
562+
sage: mat = codes.HammingCode(GF(3), 3).dual_code().generator_matrix()
563563
sage: PartitionRefinementLinearCode(mat.ncols(), mat)
564564
Canonical form algorithm for linear code generated by
565565
[1 0 1 1 0 1 0 1 1 1 0 1 1]
@@ -577,7 +577,7 @@ cdef class PartitionRefinementLinearCode(PartitionRefinement_generic):
577577
EXAMPLES::
578578
579579
sage: from sage.coding.codecan.codecan import PartitionRefinementLinearCode
580-
sage: mat = codes.HammingCode(3, GF(3)).dual_code().generator_matrix()
580+
sage: mat = codes.HammingCode(GF(3), 3).dual_code().generator_matrix()
581581
sage: P = PartitionRefinementLinearCode(mat.ncols(), mat) #indirect doctest
582582
sage: P.get_canonical_form()
583583
[1 0 0 0 0 1 1 1 1 1 1 1 1]
@@ -663,7 +663,7 @@ cdef class PartitionRefinementLinearCode(PartitionRefinement_generic):
663663
EXAMPLES::
664664
665665
sage: from sage.coding.codecan.codecan import PartitionRefinementLinearCode
666-
sage: mat = codes.HammingCode(3, GF(3)).dual_code().generator_matrix()
666+
sage: mat = codes.HammingCode(GF(3), 3).dual_code().generator_matrix()
667667
sage: P1 = PartitionRefinementLinearCode(mat.ncols(), mat)
668668
sage: CF1 = P1.get_canonical_form()
669669
sage: s = SemimonomialTransformationGroup(GF(3), mat.ncols()).an_element()
@@ -681,7 +681,7 @@ cdef class PartitionRefinementLinearCode(PartitionRefinement_generic):
681681
EXAMPLES::
682682
683683
sage: from sage.coding.codecan.codecan import PartitionRefinementLinearCode
684-
sage: mat = codes.HammingCode(3, GF(3)).dual_code().generator_matrix()
684+
sage: mat = codes.HammingCode(GF(3), 3).dual_code().generator_matrix()
685685
sage: P = PartitionRefinementLinearCode(mat.ncols(), mat)
686686
sage: CF = P.get_canonical_form()
687687
sage: t = P.get_transporter()
@@ -697,7 +697,7 @@ cdef class PartitionRefinementLinearCode(PartitionRefinement_generic):
697697
EXAMPLES::
698698
699699
sage: from sage.coding.codecan.codecan import PartitionRefinementLinearCode
700-
sage: mat = codes.HammingCode(3, GF(3)).dual_code().generator_matrix()
700+
sage: mat = codes.HammingCode(GF(3), 3).dual_code().generator_matrix()
701701
sage: P = PartitionRefinementLinearCode(mat.ncols(), mat)
702702
sage: A = P.get_autom_gens()
703703
sage: all( [(a*mat).echelon_form() == mat.echelon_form() for a in A])
@@ -713,7 +713,7 @@ cdef class PartitionRefinementLinearCode(PartitionRefinement_generic):
713713
EXAMPLES::
714714
715715
sage: from sage.coding.codecan.codecan import PartitionRefinementLinearCode
716-
sage: mat = codes.HammingCode(3, GF(3)).dual_code().generator_matrix()
716+
sage: mat = codes.HammingCode(GF(3), 3).dual_code().generator_matrix()
717717
sage: P = PartitionRefinementLinearCode(mat.ncols(), mat)
718718
sage: P.get_autom_order_inner_stabilizer()
719719
2

src/sage/coding/codes_catalog.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
CyclicCode, CyclicCodeFromCheckPolynomial, DuadicCodeEvenPair,
2323
DuadicCodeOddPair, ExtendedBinaryGolayCode,
2424
ExtendedQuadraticResidueCode, ExtendedTernaryGolayCode,
25-
HammingCode, LinearCode, LinearCodeFromCheckMatrix,
25+
LinearCode, LinearCodeFromCheckMatrix,
2626
QuadraticResidueCode, QuadraticResidueCodeEvenPair,
2727
QuadraticResidueCodeOddPair, RandomLinearCode,
2828
ReedSolomonCode, TernaryGolayCode,
@@ -31,6 +31,7 @@
3131
from grs import GeneralizedReedSolomonCode
3232

3333
from guava import BinaryReedMullerCode, QuasiQuadraticResidueCode, RandomLinearCodeGuava
34+
from hamming_code import HammingCode
3435

3536
import decoders_catalog as decoders
3637
import encoders_catalog as encoders

0 commit comments

Comments
 (0)