Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/coding/code_constructions.py
8815 views
1
r"""
2
Linear code constructions
3
4
This file contains constructions of error-correcting codes which are
5
pure Python/Sage and not obtained from wrapping GUAVA functions.
6
The GUAVA wrappers are in guava.py.
7
8
All codes available here can be accessed through the ``codes`` object::
9
10
sage: codes.HammingCode(3,GF(2))
11
Linear code of length 7, dimension 4 over Finite Field of size 2
12
13
Let `F` be a finite field with `q` elements.
14
Here's a constructive definition of a cyclic code of length
15
`n`.
16
17
#. Pick a monic polynomial `g(x)\in F[x]` dividing
18
`x^n-1`. This is called the generating polynomial of the
19
code.
20
21
#. For each polynomial `p(x)\in F[x]`, compute
22
`p(x)g(x)\ ({\rm mod}\ x^n-1)`. Denote the answer by
23
`c_0+c_1x+...+c_{n-1}x^{n-1}`.
24
25
#. `{\bf c} =(c_0,c_1,...,c_{n-1})` is a codeword in
26
`C`. Every codeword in `C` arises in this way
27
(from some `p(x)`).
28
29
The polynomial notation for the code is to call
30
`c_0+c_1x+...+c_{n-1}x^{n-1}` the codeword (instead of
31
`(c_0,c_1,...,c_{n-1})`). The polynomial
32
`h(x)=(x^n-1)/g(x)` is called the check polynomial of
33
`C`.
34
35
Let `n` be a positive integer relatively prime to
36
`q` and let `\alpha` be a primitive
37
`n`-th root of unity. Each generator polynomial `g`
38
of a cyclic code `C` of length `n` has a
39
factorization of the form
40
41
42
.. math::
43
44
g(x) = (x - \alpha^{k_1})...(x - \alpha^{k_r}),
45
46
47
where `\{k_1,...,k_r\} \subset \{0,...,n-1\}`. The
48
numbers `\alpha^{k_i}`, `1 \leq i \leq r`, are
49
called the zeros of the code `C`. Many families of cyclic
50
codes (such as BCH codes and the quadratic residue codes) are
51
defined using properties of the zeros of `C`.
52
53
- BCHCode - A 'Bose-Chaudhuri-Hockenghem code' (or BCH code for short)
54
is the largest possible cyclic code of length n over field F=GF(q),
55
whose generator polynomial has zeros (which contain the set)
56
`Z = \{a^i\ |\ i \in C_b\cup ... C_{b+delta-2}\}`, where
57
`a` is a primitive `n^{th}` root of unity in the
58
splitting field `GF(q^m)`, `b` is an integer
59
`0\leq b\leq n-delta+1` and `m` is the multiplicative
60
order of `q` modulo `n`. The default here is `b=0`
61
(unlike Guava, which has default `b=1`). Here `C_k` are
62
the cyclotomic codes (see ``cyclotomic_cosets``).
63
64
- BinaryGolayCode, ExtendedBinaryGolayCode, TernaryGolayCode,
65
ExtendedTernaryGolayCode the well-known"extremal" Golay codes,
66
http://en.wikipedia.org/wiki/Golay_code
67
68
- cyclic codes - CyclicCodeFromGeneratingPolynomial (= CyclicCode),
69
CyclicCodeFromCheckPolynomial,
70
http://en.wikipedia.org/wiki/Cyclic_code
71
72
- DuadicCodeEvenPair, DuadicCodeOddPair: Constructs the "even
73
(resp. odd) pair" of duadic codes associated to the "splitting" S1,
74
S2 of n. This is a special type of cyclic code whose generator is
75
determined by S1, S2. See chapter 6 in [HP]_.
76
77
- HammingCode - the well-known Hamming code,
78
http://en.wikipedia.org/wiki/Hamming_code
79
80
- LinearCodeFromCheckMatrix - for specifying the code using the
81
check matrix instead of the generator matrix.
82
83
- QuadraticResidueCodeEvenPair, QuadraticResidueCodeOddPair: Quadratic
84
residue codes of a given odd prime length and base ring either don't
85
exist at all or occur as 4-tuples - a pair of
86
"odd-like" codes and a pair of "even-like" codes. If n 2 is prime
87
then (Theorem 6.6.2 in [HP]_) a QR code exists over GF(q) iff q is a
88
quadratic residue mod n. Here they are constructed as"even-like"
89
duadic codes associated the splitting (Q,N) mod n, where Q is the
90
set of non-zero quadratic residues and N is the non-residues.
91
QuadraticResidueCode (a special case) and
92
ExtendedQuadraticResidueCode are included as well.
93
94
- RandomLinearCode - Repeatedly applies Sage's random_element applied
95
to the ambient MatrixSpace of the generator matrix until a full rank
96
matrix is found.
97
98
- ReedSolomonCode - Given a finite field `F` of order `q`,
99
let `n` and `k` be chosen such that
100
`1 \leq k \leq n \leq q`.
101
Pick `n` distinct elements of `F`, denoted
102
`\{ x_1, x_2, ... , x_n \}`. Then, the codewords are obtained
103
by evaluating every polynomial in `F[x]` of degree less than
104
`k` at each `x_i`.
105
106
- ToricCode - Let `P` denote a list of lattice points in
107
`\ZZ^d` and let `T` denote a listing of all
108
points in `(F^x )^d`. Put `n=|T|` and let `k`
109
denote the dimension of the vector space of functions
110
`V = \mathrm{Span} \{x^e \ |\ e \in P\}`.
111
The associated toric code `C` is
112
the evaluation code which is the image of the evaluation map
113
`eval_T : V \rightarrow F^n`, where `x^e` is the
114
multi-index notation.
115
116
- WalshCode - a binary linear `[2^m,m,2^{m-1}]` code
117
related to Hadamard matrices.
118
http://en.wikipedia.org/wiki/Walsh_code
119
120
REFERENCES:
121
122
.. [HP] W. C. Huffman, V. Pless, Fundamentals of Error-Correcting
123
Codes, Cambridge Univ. Press, 2003.
124
125
AUTHOR:
126
127
- David Joyner (2007-05): initial version
128
129
- " (2008-02): added cyclic codes, Hamming codes
130
131
- " (2008-03): added BCH code, LinearCodeFromCheckmatrix, ReedSolomonCode, WalshCode,
132
DuadicCodeEvenPair, DuadicCodeOddPair, QR codes (even and odd)
133
134
- " (2008-09) fix for bug in BCHCode reported by F. Voloch
135
136
- " (2008-10) small docstring changes to WalshCode and walsh_matrix
137
138
Functions
139
---------
140
141
"""
142
############################################################################
143
## Copyright David Joyner, 2007. [email protected].
144
## This is released under the GPL, version 2 or later (www.fsf.org).
145
#############################################################################
146
147
148
from sage.matrix.matrix_space import MatrixSpace
149
from sage.matrix.constructor import matrix
150
from sage.rings.finite_rings.constructor import FiniteField as GF
151
from sage.groups.perm_gps.permgroup_named import SymmetricGroup
152
from sage.misc.misc import prod
153
from linear_code import LinearCodeFromVectorSpace, LinearCode
154
from sage.modules.free_module import span
155
from sage.schemes.projective.projective_space import ProjectiveSpace
156
from sage.structure.sequence import Sequence
157
from sage.rings.arith import GCD,LCM,divisors,quadratic_residues
158
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
159
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
160
from sage.rings.integer import Integer
161
from sage.sets.set import Set
162
from sage.rings.finite_rings.integer_mod import Mod
163
164
############### utility functions ################
165
166
167
def cyclotomic_cosets(q, n, t = None):
168
r"""
169
INPUT: q,n,t positive integers (or t=None) Some type-checking of
170
inputs is performed.
171
172
OUTPUT: q-cyclotomic cosets mod n (or, if t is not None, the q-cyclotomic
173
coset mod n containing t)
174
175
Let q, n be relatively print positive integers and let
176
`A = q^{ZZ}`. The group A acts on ZZ/nZZ by multiplication.
177
The orbits of this action are "cyclotomic cosets", or more
178
precisely "q-cyclotomic cosets mod n". Sometimes the smallest
179
element of the coset is called the "coset leader". The algorithm
180
will always return the cosets as sorted lists of lists, so the
181
coset leader will always be the first element in the list.
182
183
These cosets arise in the theory of duadic codes and minimal
184
polynomials of finite fields. Fix a primitive element `z`
185
of `GF(q^k)`. The minimal polynomial of `z^s` over
186
`GF(q)` is given by
187
188
.. math::
189
190
M_s(x) = \prod_{i \in C_s} (x-z^i),
191
192
193
where `C_s` is the q-cyclotomic coset mod n containing s,
194
`n = q^k - 1`.
195
196
EXAMPLES::
197
198
sage: cyclotomic_cosets(2,11)
199
[[0], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]
200
sage: cyclotomic_cosets(2,15)
201
[[0], [1, 2, 4, 8], [3, 6, 9, 12], [5, 10], [7, 11, 13, 14]]
202
sage: cyclotomic_cosets(2,15,5)
203
[5, 10]
204
sage: cyclotomic_cosets(3,16)
205
[[0], [1, 3, 9, 11], [2, 6], [4, 12], [5, 7, 13, 15], [8], [10, 14]]
206
sage: F.<z> = GF(2^4, "z")
207
sage: P.<x> = PolynomialRing(F,"x")
208
sage: a = z^5
209
sage: a.minimal_polynomial()
210
x^2 + x + 1
211
sage: prod([x-z^i for i in [5, 10]])
212
x^2 + x + 1
213
sage: cyclotomic_cosets(3,2,0)
214
[0]
215
sage: cyclotomic_cosets(3,2,1)
216
[1]
217
sage: cyclotomic_cosets(3,2,2)
218
[0]
219
220
This last output looks strange but is correct, since the elements of
221
the cosets are in ZZ/nZZ and 2 = 0 in ZZ/2ZZ.
222
"""
223
from sage.misc.misc import srange
224
if t is not None and not isinstance(t, Integer):
225
raise TypeError, "Optional input %s must None or an integer."%t
226
if q<2 or n<2:
227
raise TypeError, "Inputs %s and %s must be > 1."%(q,n)
228
if GCD(q,n) != 1:
229
raise TypeError, "Inputs %s and %s must be relative prime."%(q,n)
230
if t is not None and isinstance(t, Integer):
231
S = Set([t*q**i%n for i in srange(n)])
232
L = list(S)
233
L.sort()
234
return L
235
ccs = Set([])
236
ccs_list = [[0]]
237
for s in range(1,n):
238
if not(s in ccs):
239
S = Set([s*q**i%n for i in srange(n)])
240
L = list(S)
241
L.sort()
242
ccs = ccs.union(S)
243
ccs_list.append(L)
244
return ccs_list
245
246
def is_a_splitting(S1,S2,n):
247
"""
248
INPUT: S1, S2 are disjoint sublists partitioning [1, 2, ..., n-1]
249
n1 is an integer
250
251
OUTPUT: a, b where a is True or False, depending on whether S1, S2
252
form a "splitting" of n (ie, if there is a b1 such that b\*S1=S2
253
(point-wise multiplication mod n), and b is a splitting (if a =
254
True) or 0 (if a = False)
255
256
Splittings are useful for computing idempotents in the quotient
257
ring `Q = GF(q)[x]/(x^n-1)`. For
258
259
EXAMPLES::
260
261
sage: from sage.coding.code_constructions import is_a_splitting
262
sage: n = 11; q = 3
263
sage: C = cyclotomic_cosets(q,n); C
264
[[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
265
sage: S1 = C[1]
266
sage: S2 = C[2]
267
sage: is_a_splitting(S1,S2,11)
268
(True, 2)
269
sage: F = GF(q)
270
sage: P.<x> = PolynomialRing(F,"x")
271
sage: I = Ideal(P,[x^n-1])
272
sage: Q.<x> = QuotientRing(P,I)
273
sage: i1 = -sum([x^i for i in S1]); i1
274
2*x^9 + 2*x^5 + 2*x^4 + 2*x^3 + 2*x
275
sage: i2 = -sum([x^i for i in S2]); i2
276
2*x^10 + 2*x^8 + 2*x^7 + 2*x^6 + 2*x^2
277
sage: i1^2 == i1
278
True
279
sage: i2^2 == i2
280
True
281
sage: (1-i1)^2 == 1-i1
282
True
283
sage: (1-i2)^2 == 1-i2
284
True
285
286
We return to dealing with polynomials (rather than elements of
287
quotient rings), so we can construct cyclic codes::
288
289
sage: P.<x> = PolynomialRing(F,"x")
290
sage: i1 = -sum([x^i for i in S1])
291
sage: i2 = -sum([x^i for i in S2])
292
sage: i1_sqrd = (i1^2).quo_rem(x^n-1)[1]
293
sage: i1_sqrd == i1
294
True
295
sage: i2_sqrd = (i2^2).quo_rem(x^n-1)[1]
296
sage: i2_sqrd == i2
297
True
298
sage: C1 = codes.CyclicCodeFromGeneratingPolynomial(n,i1)
299
sage: C2 = codes.CyclicCodeFromGeneratingPolynomial(n,1-i2)
300
sage: C1.dual_code() == C2
301
True
302
303
This is a special case of Theorem 6.4.3 in [HP]_.
304
"""
305
if Set(S1).union(Set(S2)) != Set(range(1,n)):
306
raise TypeError, "Lists must partition [1,2,...,n-1]."
307
if n<3:
308
raise TypeError, "Input %s must be > 2."%n
309
for b in range(2,n):
310
SS1 = Set([b*x%n for x in S1])
311
SS2 = Set([b*x%n for x in S2])
312
if SS1 == Set(S2) and SS2 == Set(S1):
313
return True, b
314
return False, 0
315
316
317
def lift2smallest_field(a):
318
"""
319
INPUT: a is an element of a finite field GF(q)
320
321
OUTPUT: the element b of the smallest subfield F of GF(q) for
322
which F(b)=a.
323
324
EXAMPLES::
325
326
sage: from sage.coding.code_constructions import lift2smallest_field
327
sage: FF.<z> = GF(3^4,"z")
328
sage: a = z^10
329
sage: lift2smallest_field(a)
330
(2*z + 1, Finite Field in z of size 3^2)
331
sage: a = z^40
332
sage: lift2smallest_field(a)
333
(2, Finite Field of size 3)
334
335
AUTHORS:
336
337
- John Cremona
338
"""
339
FF = a.parent()
340
k = FF.degree()
341
if k == 1:
342
return a, FF
343
pol = a.minimal_polynomial()
344
d = pol.degree()
345
if d == k:
346
return a, FF
347
p = FF.characteristic()
348
F = GF(p**d,"z")
349
b = pol.roots(F,multiplicities=False)[0]
350
return b, F
351
352
def lift2smallest_field2(a):
353
"""
354
INPUT: a is an element of a finite field GF(q) OUTPUT: the element
355
b of the smallest subfield F of GF(q) for which F(b)=a.
356
357
EXAMPLES::
358
359
sage: from sage.coding.code_constructions import lift2smallest_field2
360
sage: FF.<z> = GF(3^4,"z")
361
sage: a = z^40
362
sage: lift2smallest_field2(a)
363
(2, Finite Field of size 3)
364
sage: FF.<z> = GF(2^4,"z")
365
sage: a = z^15
366
sage: lift2smallest_field2(a)
367
(1, Finite Field of size 2)
368
369
.. warning::
370
371
Since coercion (the FF(b) step) has a bug in it, this
372
*only works* in the case when you *know* F is a prime field.
373
374
AUTHORS:
375
376
- David Joyner
377
"""
378
FF = a.parent()
379
q = FF.order()
380
if q.is_prime():
381
return a,FF
382
p = q.factor()[0][0]
383
k = q.factor()[0][1]
384
for d in divisors(k):
385
F = GF(p**d,"zz")
386
for b in F:
387
if FF(b) == a:
388
return b, F
389
390
391
def permutation_action(g,v):
392
"""
393
Returns permutation of rows g\*v. Works on lists, matrices,
394
sequences and vectors (by permuting coordinates). The code requires
395
switching from i to i+1 (and back again) since the SymmetricGroup
396
is, by convention, the symmetric group on the "letters" 1, 2, ...,
397
n (not 0, 1, ..., n-1).
398
399
EXAMPLES::
400
401
sage: V = VectorSpace(GF(3),5)
402
sage: v = V([0,1,2,0,1])
403
sage: G = SymmetricGroup(5)
404
sage: g = G([(1,2,3)])
405
sage: permutation_action(g,v)
406
(1, 2, 0, 0, 1)
407
sage: g = G([()])
408
sage: permutation_action(g,v)
409
(0, 1, 2, 0, 1)
410
sage: g = G([(1,2,3,4,5)])
411
sage: permutation_action(g,v)
412
(1, 2, 0, 1, 0)
413
sage: L = Sequence([1,2,3,4,5])
414
sage: permutation_action(g,L)
415
[2, 3, 4, 5, 1]
416
sage: MS = MatrixSpace(GF(3),3,7)
417
sage: A = MS([[1,0,0,0,1,1,0],[0,1,0,1,0,1,0],[0,0,0,0,0,0,1]])
418
sage: S5 = SymmetricGroup(5)
419
sage: g = S5([(1,2,3)])
420
sage: A
421
[1 0 0 0 1 1 0]
422
[0 1 0 1 0 1 0]
423
[0 0 0 0 0 0 1]
424
sage: permutation_action(g,A)
425
[0 1 0 1 0 1 0]
426
[0 0 0 0 0 0 1]
427
[1 0 0 0 1 1 0]
428
429
It also works on lists and is a "left action"::
430
431
sage: v = [0,1,2,0,1]
432
sage: G = SymmetricGroup(5)
433
sage: g = G([(1,2,3)])
434
sage: gv = permutation_action(g,v); gv
435
[1, 2, 0, 0, 1]
436
sage: permutation_action(g,v) == g(v)
437
True
438
sage: h = G([(3,4)])
439
sage: gv = permutation_action(g,v)
440
sage: hgv = permutation_action(h,gv)
441
sage: hgv == permutation_action(h*g,v)
442
True
443
444
AUTHORS:
445
446
- David Joyner, licensed under the GPL v2 or greater.
447
"""
448
v_type_list = False
449
if type(v) == list:
450
v_type_list = True
451
v = Sequence(v)
452
V = v.parent()
453
n = len(list(v))
454
gv = []
455
for i in range(n):
456
gv.append(v[g(i+1)-1])
457
if v_type_list:
458
return gv
459
return V(gv)
460
461
def walsh_matrix(m0):
462
"""
463
This is the generator matrix of a Walsh code. The matrix of
464
codewords correspond to a Hadamard matrix.
465
466
EXAMPLES::
467
468
sage: walsh_matrix(2)
469
[0 0 1 1]
470
[0 1 0 1]
471
sage: walsh_matrix(3)
472
[0 0 0 0 1 1 1 1]
473
[0 0 1 1 0 0 1 1]
474
[0 1 0 1 0 1 0 1]
475
sage: C = LinearCode(walsh_matrix(4)); C
476
Linear code of length 16, dimension 4 over Finite Field of size 2
477
sage: C.spectrum()
478
[1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 0]
479
480
This last code has minimum distance 8.
481
482
REFERENCES:
483
484
- http://en.wikipedia.org/wiki/Hadamard_matrix
485
"""
486
m = int(m0)
487
if m == 1:
488
return matrix(GF(2), 1, 2, [ 0, 1])
489
if m > 1:
490
row2 = [x.list() for x in walsh_matrix(m-1).augment(walsh_matrix(m-1)).rows()]
491
return matrix(GF(2), m, 2**m, [[0]*2**(m-1) + [1]*2**(m-1)] + row2)
492
raise ValueError, "%s must be an integer > 0."%m0
493
494
495
##################### main constructions #####################
496
497
498
499
def BCHCode(n,delta,F,b=0):
500
r"""
501
A 'Bose-Chaudhuri-Hockenghem code' (or BCH code for short) is the
502
largest possible cyclic code of length n over field F=GF(q), whose
503
generator polynomial has zeros (which contain the set)
504
`Z = \{a^{b},a^{b+1}, ..., a^{b+delta-2}\}`, where a is a
505
primitive `n^{th}` root of unity in the splitting field
506
`GF(q^m)`, b is an integer `0\leq b\leq n-delta+1`
507
and m is the multiplicative order of q modulo n. (The integers
508
`b,...,b+delta-2` typically lie in the range
509
`1,...,n-1`.) The integer `delta \geq 1` is called
510
the "designed distance". The length n of the code and the size q of
511
the base field must be relatively prime. The generator polynomial
512
is equal to the least common multiple of the minimal polynomials of
513
the elements of the set `Z` above.
514
515
Special cases are b=1 (resulting codes are called 'narrow-sense'
516
BCH codes), and `n=q^m-1` (known as 'primitive' BCH
517
codes).
518
519
It may happen that several values of delta give rise to the same
520
BCH code. The largest one is called the Bose distance of the code.
521
The true minimum distance, d, of the code is greater than or equal
522
to the Bose distance, so `d\geq delta`.
523
524
EXAMPLES::
525
526
sage: FF.<a> = GF(3^2,"a")
527
sage: x = PolynomialRing(FF,"x").gen()
528
sage: L = [b.minpoly() for b in [a,a^2,a^3]]; g = LCM(L)
529
sage: f = x^(8)-1
530
sage: g.divides(f)
531
True
532
sage: C = codes.CyclicCode(8,g); C
533
Linear code of length 8, dimension 4 over Finite Field of size 3
534
sage: C.minimum_distance()
535
4
536
sage: C = codes.BCHCode(8,3,GF(3),1); C
537
Linear code of length 8, dimension 4 over Finite Field of size 3
538
sage: C.minimum_distance()
539
4
540
sage: C = codes.BCHCode(8,3,GF(3)); C
541
Linear code of length 8, dimension 5 over Finite Field of size 3
542
sage: C.minimum_distance()
543
3
544
sage: C = codes.BCHCode(26, 5, GF(5), b=1); C
545
Linear code of length 26, dimension 10 over Finite Field of size 5
546
547
"""
548
from sage.misc.misc import srange
549
q = F.order()
550
R = IntegerModRing(n)
551
m = R(q).multiplicative_order()
552
FF = GF(q**m,"z")
553
z = FF.gen()
554
e = z.multiplicative_order()/n
555
a = z**e # order n
556
P = PolynomialRing(F,"x")
557
x = P.gen()
558
cosets = Set([])
559
for i in srange(b,b+delta-1):
560
cosets = cosets.union(Set(cyclotomic_cosets(q, n, i)))
561
L0 = [a**j for j in cosets]
562
L1 = [P(ai.minpoly()) for ai in L0]
563
g = P(LCM(L1))
564
#print cosets, "\n", g, "\n", (x**n-1).factor(), "\n", L1, "\n", g.divides(x**n-1)
565
if not(g.divides(x**n-1)):
566
raise ValueError, "BCH codes does not exist with the given input."
567
return CyclicCodeFromGeneratingPolynomial(n,g)
568
569
570
def BinaryGolayCode():
571
r"""
572
BinaryGolayCode() returns a binary Golay code. This is a perfect
573
[23,12,7] code. It is also (equivalent to) a cyclic code, with
574
generator polynomial
575
`g(x)=1+x^2+x^4+x^5+x^6+x^{10}+x^{11}`. Extending it yields
576
the extended Golay code (see ExtendedBinaryGolayCode).
577
578
EXAMPLE::
579
580
sage: C = codes.BinaryGolayCode()
581
sage: C
582
Linear code of length 23, dimension 12 over Finite Field of size 2
583
sage: C.minimum_distance()
584
7
585
sage: C.minimum_distance(algorithm='gap') # long time, check d=7
586
7
587
588
AUTHORS:
589
590
- David Joyner (2007-05)
591
"""
592
F = GF(2)
593
B = [[1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\
594
[0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\
595
[0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],\
596
[0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\
597
[0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],\
598
[0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0],\
599
[0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0],\
600
[0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0],\
601
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0],\
602
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0],\
603
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0],\
604
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1]]
605
# MS = MatrixSpace(F,12,23)
606
# V = VectorSpace(F,23)
607
V = span(B, F)
608
return LinearCodeFromVectorSpace(V, d=7)
609
610
611
def CyclicCodeFromGeneratingPolynomial(n,g,ignore=True):
612
r"""
613
If g is a polynomial over GF(q) which divides `x^n-1` then
614
this constructs the code "generated by g" (ie, the code associated
615
with the principle ideal `gR` in the ring
616
`R = GF(q)[x]/(x^n-1)` in the usual way).
617
618
The option "ignore" says to ignore the condition that (a) the
619
characteristic of the base field does not divide the length (the
620
usual assumption in the theory of cyclic codes), and (b) `g`
621
must divide `x^n-1`. If ignore=True, instead of returning
622
an error, a code generated by `gcd(x^n-1,g)` is created.
623
624
EXAMPLES::
625
626
sage: P.<x> = PolynomialRing(GF(3),"x")
627
sage: g = x-1
628
sage: C = codes.CyclicCodeFromGeneratingPolynomial(4,g); C
629
Linear code of length 4, dimension 3 over Finite Field of size 3
630
sage: P.<x> = PolynomialRing(GF(4,"a"),"x")
631
sage: g = x^3+1
632
sage: C = codes.CyclicCodeFromGeneratingPolynomial(9,g); C
633
Linear code of length 9, dimension 6 over Finite Field in a of size 2^2
634
sage: P.<x> = PolynomialRing(GF(2),"x")
635
sage: g = x^3+x+1
636
sage: C = codes.CyclicCodeFromGeneratingPolynomial(7,g); C
637
Linear code of length 7, dimension 4 over Finite Field of size 2
638
sage: C.gen_mat()
639
[1 1 0 1 0 0 0]
640
[0 1 1 0 1 0 0]
641
[0 0 1 1 0 1 0]
642
[0 0 0 1 1 0 1]
643
sage: g = x+1
644
sage: C = codes.CyclicCodeFromGeneratingPolynomial(4,g); C
645
Linear code of length 4, dimension 3 over Finite Field of size 2
646
sage: C.gen_mat()
647
[1 1 0 0]
648
[0 1 1 0]
649
[0 0 1 1]
650
651
On the other hand, CyclicCodeFromPolynomial(4,x) will produce a
652
ValueError including a traceback error message: "`x` must
653
divide `x^4 - 1`". You will also get a ValueError if you
654
type
655
656
::
657
658
sage: P.<x> = PolynomialRing(GF(4,"a"),"x")
659
sage: g = x^2+1
660
661
followed by CyclicCodeFromGeneratingPolynomial(6,g). You will also
662
get a ValueError if you type
663
664
::
665
666
sage: P.<x> = PolynomialRing(GF(3),"x")
667
sage: g = x^2-1
668
sage: C = codes.CyclicCodeFromGeneratingPolynomial(5,g); C
669
Linear code of length 5, dimension 4 over Finite Field of size 3
670
671
followed by C = CyclicCodeFromGeneratingPolynomial(5,g,False), with
672
a traceback message including "`x^2 + 2` must divide
673
`x^5 - 1`".
674
"""
675
P = g.parent()
676
x = P.gen()
677
F = g.base_ring()
678
p = F.characteristic()
679
if not(ignore) and p.divides(n):
680
raise ValueError, 'The characteristic %s must not divide %s'%(p,n)
681
if not(ignore) and not(g.divides(x**n-1)):
682
raise ValueError, '%s must divide x^%s - 1'%(g,n)
683
gn = GCD([g,x**n-1])
684
d = gn.degree()
685
coeffs = Sequence(gn.list())
686
r1 = Sequence(coeffs+[0]*(n - d - 1))
687
Sn = SymmetricGroup(n)
688
s = Sn.gens()[0] # assumes 1st gen of S_n is (1,2,...,n)
689
rows = [permutation_action(s**(-i),r1) for i in range(n-d)]
690
MS = MatrixSpace(F,n-d,n)
691
return LinearCode(MS(rows))
692
693
CyclicCode = CyclicCodeFromGeneratingPolynomial
694
695
def CyclicCodeFromCheckPolynomial(n,h,ignore=True):
696
r"""
697
If h is a polynomial over GF(q) which divides `x^n-1` then
698
this constructs the code "generated by `g = (x^n-1)/h`"
699
(ie, the code associated with the principle ideal `gR` in
700
the ring `R = GF(q)[x]/(x^n-1)` in the usual way). The
701
option "ignore" says to ignore the condition that the
702
characteristic of the base field does not divide the length (the
703
usual assumption in the theory of cyclic codes).
704
705
EXAMPLES::
706
707
sage: P.<x> = PolynomialRing(GF(3),"x")
708
sage: C = codes.CyclicCodeFromCheckPolynomial(4,x + 1); C
709
Linear code of length 4, dimension 1 over Finite Field of size 3
710
sage: C = codes.CyclicCodeFromCheckPolynomial(4,x^3 + x^2 + x + 1); C
711
Linear code of length 4, dimension 3 over Finite Field of size 3
712
sage: C.gen_mat()
713
[2 1 0 0]
714
[0 2 1 0]
715
[0 0 2 1]
716
"""
717
P = h.parent()
718
x = P.gen()
719
d = h.degree()
720
F = h.base_ring()
721
p = F.characteristic()
722
if not(ignore) and p.divides(n):
723
raise ValueError, 'The characteristic %s must not divide %s'%(p,n)
724
if not(h.divides(x**n-1)):
725
raise ValueError, '%s must divide x^%s - 1'%(h,n)
726
g = P((x**n-1)/h)
727
return CyclicCodeFromGeneratingPolynomial(n,g)
728
729
def DuadicCodeEvenPair(F,S1,S2):
730
r"""
731
Constructs the "even pair" of duadic codes associated to the
732
"splitting" (see the docstring for ``is_a_splitting``
733
for the definition) S1, S2 of n.
734
735
.. warning::
736
737
Maybe the splitting should be associated to a sum of
738
q-cyclotomic cosets mod n, where q is a *prime*.
739
740
EXAMPLES::
741
742
sage: from sage.coding.code_constructions import is_a_splitting
743
sage: n = 11; q = 3
744
sage: C = cyclotomic_cosets(q,n); C
745
[[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
746
sage: S1 = C[1]
747
sage: S2 = C[2]
748
sage: is_a_splitting(S1,S2,11)
749
(True, 2)
750
sage: codes.DuadicCodeEvenPair(GF(q),S1,S2)
751
(Linear code of length 11, dimension 5 over Finite Field of size 3,
752
Linear code of length 11, dimension 5 over Finite Field of size 3)
753
"""
754
n = max(S1+S2)+1
755
if not(is_a_splitting(S1,S2,n)):
756
raise TypeError, "%s, %s must be a splitting of %s."%(S1,S2,n)
757
q = F.order()
758
k = Mod(q,n).multiplicative_order()
759
FF = GF(q**k,"z")
760
z = FF.gen()
761
zeta = z**((q**k-1)/n)
762
P1 = PolynomialRing(FF,"x")
763
x = P1.gen()
764
g1 = prod([x-zeta**i for i in S1+[0]])
765
g2 = prod([x-zeta**i for i in S2+[0]])
766
P2 = PolynomialRing(F,"x")
767
x = P2.gen()
768
gg1 = P2([lift2smallest_field(c)[0] for c in g1.coeffs()])
769
gg2 = P2([lift2smallest_field(c)[0] for c in g2.coeffs()])
770
C1 = CyclicCodeFromGeneratingPolynomial(n,gg1)
771
C2 = CyclicCodeFromGeneratingPolynomial(n,gg2)
772
return C1,C2
773
774
def DuadicCodeOddPair(F,S1,S2):
775
"""
776
Constructs the "odd pair" of duadic codes associated to the
777
"splitting" S1, S2 of n.
778
779
.. warning::
780
781
Maybe the splitting should be associated to a sum of
782
q-cyclotomic cosets mod n, where q is a *prime*.
783
784
EXAMPLES::
785
786
sage: from sage.coding.code_constructions import is_a_splitting
787
sage: n = 11; q = 3
788
sage: C = cyclotomic_cosets(q,n); C
789
[[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
790
sage: S1 = C[1]
791
sage: S2 = C[2]
792
sage: is_a_splitting(S1,S2,11)
793
(True, 2)
794
sage: codes.DuadicCodeOddPair(GF(q),S1,S2)
795
(Linear code of length 11, dimension 6 over Finite Field of size 3,
796
Linear code of length 11, dimension 6 over Finite Field of size 3)
797
798
This is consistent with Theorem 6.1.3 in [HP]_.
799
"""
800
n = max(S1+S2)+1
801
if not(is_a_splitting(S1,S2,n)):
802
raise TypeError, "%s, %s must be a splitting of %s."%(S1,S2,n)
803
q = F.order()
804
k = Mod(q,n).multiplicative_order()
805
FF = GF(q**k,"z")
806
z = FF.gen()
807
zeta = z**((q**k-1)/n)
808
P1 = PolynomialRing(FF,"x")
809
x = P1.gen()
810
g1 = prod([x-zeta**i for i in S1+[0]])
811
g2 = prod([x-zeta**i for i in S2+[0]])
812
j = sum([x**i/n for i in range(n)])
813
P2 = PolynomialRing(F,"x")
814
x = P2.gen()
815
coeffs1 = [lift2smallest_field(c)[0] for c in (g1+j).coeffs()]
816
coeffs2 = [lift2smallest_field(c)[0] for c in (g2+j).coeffs()]
817
gg1 = P2(coeffs1)
818
gg2 = P2(coeffs2)
819
C1 = CyclicCodeFromGeneratingPolynomial(n,gg1)
820
C2 = CyclicCodeFromGeneratingPolynomial(n,gg2)
821
return C1,C2
822
823
824
def ExtendedBinaryGolayCode():
825
"""
826
ExtendedBinaryGolayCode() returns the extended binary Golay code.
827
This is a perfect [24,12,8] code. This code is self-dual.
828
829
EXAMPLES::
830
831
sage: C = codes.ExtendedBinaryGolayCode()
832
sage: C
833
Linear code of length 24, dimension 12 over Finite Field of size 2
834
sage: C.minimum_distance()
835
8
836
sage: C.minimum_distance(algorithm='gap') # long time, check d=8
837
8
838
839
AUTHORS:
840
841
- David Joyner (2007-05)
842
"""
843
B = [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1],\
844
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0],\
845
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1],\
846
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0],\
847
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1],\
848
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1],\
849
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1],\
850
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0],\
851
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0],\
852
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0],\
853
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1],\
854
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1]]
855
V = span(B, GF(2))
856
return LinearCodeFromVectorSpace(V, d=8)
857
# C = BinaryGolayCode()
858
# return C.extended_code()
859
860
861
def ExtendedQuadraticResidueCode(n,F):
862
r"""
863
The extended quadratic residue code (or XQR code) is obtained from
864
a QR code by adding a check bit to the last coordinate. (These
865
codes have very remarkable properties such as large automorphism
866
groups and duality properties - see [HP]_, Section 6.6.3-6.6.4.)
867
868
INPUT:
869
870
871
- ``n`` - an odd prime
872
873
- ``F`` - a finite prime field F whose order must be a
874
quadratic residue modulo n.
875
876
877
OUTPUT: Returns an extended quadratic residue code.
878
879
EXAMPLES::
880
881
sage: C1 = codes.QuadraticResidueCode(7,GF(2))
882
sage: C2 = C1.extended_code()
883
sage: C3 = codes.ExtendedQuadraticResidueCode(7,GF(2)); C3
884
Linear code of length 8, dimension 4 over Finite Field of size 2
885
sage: C2 == C3
886
True
887
sage: C = codes.ExtendedQuadraticResidueCode(17,GF(2))
888
sage: C
889
Linear code of length 18, dimension 9 over Finite Field of size 2
890
sage: C3 = codes.QuadraticResidueCodeOddPair(7,GF(2))[0]
891
sage: C3x = C3.extended_code()
892
sage: C4 = codes.ExtendedQuadraticResidueCode(7,GF(2))
893
sage: C3x == C4
894
True
895
896
AUTHORS:
897
898
- David Joyner (07-2006)
899
"""
900
C = QuadraticResidueCodeOddPair(n,F)[0]
901
return C.extended_code()
902
903
def ExtendedTernaryGolayCode():
904
"""
905
ExtendedTernaryGolayCode returns a ternary Golay code. This is a
906
self-dual perfect [12,6,6] code.
907
908
EXAMPLES::
909
910
sage: C = codes.ExtendedTernaryGolayCode()
911
sage: C
912
Linear code of length 12, dimension 6 over Finite Field of size 3
913
sage: C.minimum_distance()
914
6
915
sage: C.minimum_distance(algorithm='gap') # long time, check d=6
916
6
917
918
AUTHORS:
919
920
- David Joyner (11-2005)
921
"""
922
B = [[1, 0, 0, 0, 0, 0, 2, 0, 1, 2, 1, 2],\
923
[0, 1, 0, 0, 0, 0, 1, 2, 2, 2, 1, 0],\
924
[0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1],\
925
[0, 0, 0, 1, 0, 0, 1, 1, 0, 2, 2, 2],\
926
[0, 0, 0, 0, 1, 0, 2, 1, 2, 2, 0, 1],\
927
[0, 0, 0, 0, 0, 1, 0, 2, 1, 2, 2, 1]]
928
V = span(B, GF(3))
929
return LinearCodeFromVectorSpace(V, d=6)
930
# C = TernaryGolayCode()
931
# return C.extended_code()
932
933
def HammingCode(r,F):
934
r"""
935
Implements the Hamming codes.
936
937
The `r^{th}` Hamming code over `F=GF(q)` is an
938
`[n,k,d]` code with length `n=(q^r-1)/(q-1)`,
939
dimension `k=(q^r-1)/(q-1) - r` and minimum distance
940
`d=3`. The parity check matrix of a Hamming code has rows
941
consisting of all nonzero vectors of length r in its columns,
942
modulo a scalar factor so no parallel columns arise. A Hamming code
943
is a single error-correcting code.
944
945
INPUT:
946
947
948
- ``r`` - an integer 2
949
950
- ``F`` - a finite field.
951
952
953
OUTPUT: Returns the r-th q-ary Hamming code.
954
955
EXAMPLES::
956
957
sage: codes.HammingCode(3,GF(2))
958
Linear code of length 7, dimension 4 over Finite Field of size 2
959
sage: C = codes.HammingCode(3,GF(3)); C
960
Linear code of length 13, dimension 10 over Finite Field of size 3
961
sage: C.minimum_distance()
962
3
963
sage: C.minimum_distance(algorithm='gap') # long time, check d=3
964
3
965
sage: C = codes.HammingCode(3,GF(4,'a')); C
966
Linear code of length 21, dimension 18 over Finite Field in a of size 2^2
967
968
While the ``codes`` object now gathers all code constructors,
969
``HammingCode`` is still available in the global namespace::
970
971
sage: HammingCode(3,GF(2))
972
doctest:1: DeprecationWarning: This method soon will not be available in that way anymore. To use it, you can now call it by typing codes.HammingCode
973
See http://trac.sagemath.org/15445 for details.
974
Linear code of length 7, dimension 4 over Finite Field of size 2
975
976
"""
977
q = F.order()
978
n = (q**r-1)/(q-1)
979
k = n-r
980
MS = MatrixSpace(F,n,r)
981
X = ProjectiveSpace(r-1,F)
982
PFn = [list(p) for p in X.point_set(F).points(F)]
983
H = MS(PFn).transpose()
984
Cd = LinearCode(H)
985
# Hamming code always has distance 3, so we provide the distance.
986
return LinearCode(Cd.dual_code().gen_mat(), d=3)
987
988
989
def LinearCodeFromCheckMatrix(H):
990
r"""
991
A linear [n,k]-code C is uniquely determined by its generator
992
matrix G and check matrix H. We have the following short exact
993
sequence
994
995
.. math::
996
997
0 \rightarrow
998
{\mathbf{F}}^k \stackrel{G}{\rightarrow}
999
{\mathbf{F}}^n \stackrel{H}{\rightarrow}
1000
{\mathbf{F}}^{n-k} \rightarrow
1001
0.
1002
1003
("Short exact" means (a) the arrow `G` is injective, i.e.,
1004
`G` is a full-rank `k\times n` matrix, (b) the
1005
arrow `H` is surjective, and (c)
1006
`{\rm image}(G)={\rm kernel}(H)`.)
1007
1008
EXAMPLES::
1009
1010
sage: C = codes.HammingCode(3,GF(2))
1011
sage: H = C.check_mat(); H
1012
[1 0 1 0 1 0 1]
1013
[0 1 1 0 0 1 1]
1014
[0 0 0 1 1 1 1]
1015
sage: codes.LinearCodeFromCheckMatrix(H) == C
1016
True
1017
sage: C = codes.HammingCode(2,GF(3))
1018
sage: H = C.check_mat(); H
1019
[1 0 1 1]
1020
[0 1 1 2]
1021
sage: codes.LinearCodeFromCheckMatrix(H) == C
1022
True
1023
sage: C = codes.RandomLinearCode(10,5,GF(4,"a"))
1024
sage: H = C.check_mat()
1025
sage: codes.LinearCodeFromCheckMatrix(H) == C
1026
True
1027
"""
1028
Cd = LinearCode(H)
1029
return Cd.dual_code()
1030
1031
def QuadraticResidueCode(n,F):
1032
r"""
1033
A quadratic residue code (or QR code) is a cyclic code whose
1034
generator polynomial is the product of the polynomials
1035
`x-\alpha^i` (`\alpha` is a primitive
1036
`n^{th}` root of unity; `i` ranges over the set of
1037
quadratic residues modulo `n`).
1038
1039
See QuadraticResidueCodeEvenPair and QuadraticResidueCodeOddPair
1040
for a more general construction.
1041
1042
INPUT:
1043
1044
1045
- ``n`` - an odd prime
1046
1047
- ``F`` - a finite prime field F whose order must be a
1048
quadratic residue modulo n.
1049
1050
1051
OUTPUT: Returns a quadratic residue code.
1052
1053
EXAMPLES::
1054
1055
sage: C = codes.QuadraticResidueCode(7,GF(2))
1056
sage: C
1057
Linear code of length 7, dimension 4 over Finite Field of size 2
1058
sage: C = codes.QuadraticResidueCode(17,GF(2))
1059
sage: C
1060
Linear code of length 17, dimension 9 over Finite Field of size 2
1061
sage: C1 = codes.QuadraticResidueCodeOddPair(7,GF(2))[0]
1062
sage: C2 = codes.QuadraticResidueCode(7,GF(2))
1063
sage: C1 == C2
1064
True
1065
sage: C1 = codes.QuadraticResidueCodeOddPair(17,GF(2))[0]
1066
sage: C2 = codes.QuadraticResidueCode(17,GF(2))
1067
sage: C1 == C2
1068
True
1069
1070
AUTHORS:
1071
1072
- David Joyner (11-2005)
1073
"""
1074
return QuadraticResidueCodeOddPair(n,F)[0]
1075
1076
def QuadraticResidueCodeEvenPair(n,F):
1077
"""
1078
Quadratic residue codes of a given odd prime length and base ring
1079
either don't exist at all or occur as 4-tuples - a pair of
1080
"odd-like" codes and a pair of "even-like" codes. If n 2 is prime
1081
then (Theorem 6.6.2 in [HP]_) a QR code exists over GF(q) iff q is a
1082
quadratic residue mod n.
1083
1084
They are constructed as "even-like" duadic codes associated the
1085
splitting (Q,N) mod n, where Q is the set of non-zero quadratic
1086
residues and N is the non-residues.
1087
1088
EXAMPLES::
1089
1090
sage: codes.QuadraticResidueCodeEvenPair(17,GF(13))
1091
(Linear code of length 17, dimension 8 over Finite Field of size 13,
1092
Linear code of length 17, dimension 8 over Finite Field of size 13)
1093
sage: codes.QuadraticResidueCodeEvenPair(17,GF(2))
1094
(Linear code of length 17, dimension 8 over Finite Field of size 2,
1095
Linear code of length 17, dimension 8 over Finite Field of size 2)
1096
sage: codes.QuadraticResidueCodeEvenPair(13,GF(9,"z"))
1097
(Linear code of length 13, dimension 6 over Finite Field in z of size 3^2,
1098
Linear code of length 13, dimension 6 over Finite Field in z of size 3^2)
1099
sage: C1 = codes.QuadraticResidueCodeEvenPair(7,GF(2))[0]
1100
sage: C1.is_self_orthogonal()
1101
True
1102
sage: C2 = codes.QuadraticResidueCodeEvenPair(7,GF(2))[1]
1103
sage: C2.is_self_orthogonal()
1104
True
1105
sage: C3 = codes.QuadraticResidueCodeOddPair(17,GF(2))[0]
1106
sage: C4 = codes.QuadraticResidueCodeEvenPair(17,GF(2))[1]
1107
sage: C3 == C4.dual_code()
1108
True
1109
1110
This is consistent with Theorem 6.6.9 and Exercise 365 in [HP]_.
1111
"""
1112
q = F.order()
1113
Q = quadratic_residues(n); Q.remove(0) # non-zero quad residues
1114
N = range(1,n); tmp = [N.remove(x) for x in Q] # non-zero quad non-residues
1115
if (n.is_prime() and n>2 and not(q in Q)):
1116
raise ValueError, "No quadratic residue code exists for these parameters."
1117
if not(is_a_splitting(Q,N,n)):
1118
raise TypeError, "No quadratic residue code exists for these parameters."
1119
return DuadicCodeEvenPair(F,Q,N)
1120
1121
1122
def QuadraticResidueCodeOddPair(n,F):
1123
"""
1124
Quadratic residue codes of a given odd prime length and base ring
1125
either don't exist at all or occur as 4-tuples - a pair of
1126
"odd-like" codes and a pair of "even-like" codes. If n 2 is prime
1127
then (Theorem 6.6.2 in [HP]_) a QR code exists over GF(q) iff q is a
1128
quadratic residue mod n.
1129
1130
They are constructed as "odd-like" duadic codes associated the
1131
splitting (Q,N) mod n, where Q is the set of non-zero quadratic
1132
residues and N is the non-residues.
1133
1134
EXAMPLES::
1135
1136
sage: codes.QuadraticResidueCodeOddPair(17,GF(13))
1137
(Linear code of length 17, dimension 9 over Finite Field of size 13,
1138
Linear code of length 17, dimension 9 over Finite Field of size 13)
1139
sage: codes.QuadraticResidueCodeOddPair(17,GF(2))
1140
(Linear code of length 17, dimension 9 over Finite Field of size 2,
1141
Linear code of length 17, dimension 9 over Finite Field of size 2)
1142
sage: codes.QuadraticResidueCodeOddPair(13,GF(9,"z"))
1143
(Linear code of length 13, dimension 7 over Finite Field in z of size 3^2,
1144
Linear code of length 13, dimension 7 over Finite Field in z of size 3^2)
1145
sage: C1 = codes.QuadraticResidueCodeOddPair(17,GF(2))[1]
1146
sage: C1x = C1.extended_code()
1147
sage: C2 = codes.QuadraticResidueCodeOddPair(17,GF(2))[0]
1148
sage: C2x = C2.extended_code()
1149
sage: C2x.spectrum(); C1x.spectrum()
1150
[1, 0, 0, 0, 0, 0, 102, 0, 153, 0, 153, 0, 102, 0, 0, 0, 0, 0, 1]
1151
[1, 0, 0, 0, 0, 0, 102, 0, 153, 0, 153, 0, 102, 0, 0, 0, 0, 0, 1]
1152
sage: C2x == C1x.dual_code()
1153
True
1154
sage: C3 = codes.QuadraticResidueCodeOddPair(7,GF(2))[0]
1155
sage: C3x = C3.extended_code()
1156
sage: C3x.spectrum()
1157
[1, 0, 0, 0, 14, 0, 0, 0, 1]
1158
sage: C3x.is_self_dual()
1159
True
1160
1161
This is consistent with Theorem 6.6.14 in [HP]_.
1162
"""
1163
from sage.coding.code_constructions import is_a_splitting
1164
q = F.order()
1165
Q = quadratic_residues(n); Q.remove(0) # non-zero quad residues
1166
N = range(1,n); tmp = [N.remove(x) for x in Q] # non-zero quad non-residues
1167
if (n.is_prime() and n>2 and not(q in Q)):
1168
raise ValueError, "No quadratic residue code exists for these parameters."
1169
if not(is_a_splitting(Q,N,n)):
1170
raise TypeError, "No quadratic residue code exists for these parameters."
1171
return DuadicCodeOddPair(F,Q,N)
1172
1173
1174
def RandomLinearCode(n,k,F):
1175
r"""
1176
The method used is to first construct a `k \times n`
1177
matrix using Sage's random_element method for the MatrixSpace
1178
class. The construction is probabilistic but should only fail
1179
extremely rarely.
1180
1181
INPUT: Integers n,k, with `n>k`, and a finite field F
1182
1183
OUTPUT: Returns a "random" linear code with length n, dimension k
1184
over field F.
1185
1186
EXAMPLES::
1187
1188
sage: C = codes.RandomLinearCode(30,15,GF(2))
1189
sage: C
1190
Linear code of length 30, dimension 15 over Finite Field of size 2
1191
sage: C = codes.RandomLinearCode(10,5,GF(4,'a'))
1192
sage: C
1193
Linear code of length 10, dimension 5 over Finite Field in a of size 2^2
1194
1195
AUTHORS:
1196
1197
- David Joyner (2007-05)
1198
"""
1199
MS = MatrixSpace(F,k,n)
1200
for i in range(50):
1201
G = MS.random_element()
1202
if G.rank() == k:
1203
V = span(G.rows(), F)
1204
return LinearCodeFromVectorSpace(V) # may not be in standard form
1205
MS1 = MatrixSpace(F,k,k)
1206
MS2 = MatrixSpace(F,k,n-k)
1207
Ik = MS1.identity_matrix()
1208
A = MS2.random_element()
1209
G = Ik.augment(A)
1210
return LinearCode(G) # in standard form
1211
1212
1213
def ReedSolomonCode(n,k,F,pts = None):
1214
r"""
1215
Given a finite field `F` of order `q`, let
1216
`n` and `k` be chosen such that
1217
`1 \leq k \leq n \leq q`. Pick `n` distinct
1218
elements of `F`, denoted
1219
`\{ x_1, x_2, ... , x_n \}`. Then, the codewords are
1220
obtained by evaluating every polynomial in `F[x]` of degree
1221
less than `k` at each `x_i`:
1222
1223
.. math::
1224
1225
C = \left\{ \left( f(x_1), f(x_2), ..., f(x_n) \right), f \in F[x],
1226
{\rm deg}(f)<k \right\}.
1227
1228
1229
`C` is a `[n, k, n-k+1]` code. (In particular, `C` is MDS.)
1230
1231
INPUT: n : the length k : the dimension F : the base ring pts :
1232
(optional) list of n points in F (if None then Sage picks n of them
1233
in the order given to the elements of F)
1234
1235
EXAMPLES::
1236
1237
sage: C = codes.ReedSolomonCode(6,4,GF(7)); C
1238
Linear code of length 6, dimension 4 over Finite Field of size 7
1239
sage: C.minimum_distance()
1240
3
1241
sage: C = codes.ReedSolomonCode(6,4,GF(8,"a")); C
1242
Linear code of length 6, dimension 4 over Finite Field in a of size 2^3
1243
sage: C.minimum_distance()
1244
3
1245
sage: C.minimum_distance(algorithm='gap') # long time, check d=n-k+1
1246
3
1247
sage: F.<a> = GF(3^2,"a")
1248
sage: pts = [0,1,a,a^2,2*a,2*a+1]
1249
sage: len(Set(pts)) == 6 # to make sure there are no duplicates
1250
True
1251
sage: C = codes.ReedSolomonCode(6,4,F,pts); C
1252
Linear code of length 6, dimension 4 over Finite Field in a of size 3^2
1253
sage: C.minimum_distance()
1254
3
1255
1256
While the ``codes`` object now gathers all code constructors,
1257
``ReedSolomonCode`` is still available in the global namespace::
1258
1259
sage: ReedSolomonCode(6,4,GF(7))
1260
doctest:1: DeprecationWarning: This method soon will not be available in that way anymore. To use it, you can now call it by typing codes.ReedSolomonCode
1261
See http://trac.sagemath.org/15445 for details.
1262
Linear code of length 6, dimension 4 over Finite Field of size 7
1263
1264
REFERENCES:
1265
1266
- [W] http://en.wikipedia.org/wiki/Reed-Solomon
1267
"""
1268
q = F.order()
1269
power = lambda x,n,F: (x==0 and n==0) and F(1) or F(x**n) # since 0^0 is undefined
1270
if n>q or k>n or k>q:
1271
raise ValueError, "RS codes does not exist with the given input."
1272
if not(pts == None) and not(len(pts)==n):
1273
raise ValueError, "You must provide exactly %s distinct points of %s"%(n,F)
1274
if (pts == None):
1275
pts = []
1276
i = 0
1277
for x in F:
1278
if i<n:
1279
pts.append(x)
1280
i = i+1
1281
MS = MatrixSpace(F, k, n)
1282
rowsG = []
1283
rowsG = [[power(x,j,F) for x in pts] for j in range(k)]
1284
G = MS(rowsG)
1285
return LinearCode(G, d=n-k+1)
1286
1287
1288
def TernaryGolayCode():
1289
r"""
1290
TernaryGolayCode returns a ternary Golay code. This is a perfect
1291
[11,6,5] code. It is also equivalent to a cyclic code, with
1292
generator polynomial `g(x)=2+x^2+2x^3+x^4+x^5`.
1293
1294
EXAMPLES::
1295
1296
sage: C = codes.TernaryGolayCode()
1297
sage: C
1298
Linear code of length 11, dimension 6 over Finite Field of size 3
1299
sage: C.minimum_distance()
1300
5
1301
sage: C.minimum_distance(algorithm='gap') # long time, check d=5
1302
5
1303
1304
AUTHORS:
1305
1306
- David Joyner (2007-5)
1307
"""
1308
F = GF(3)
1309
B = [[2, 0, 1, 2, 1, 1, 0, 0, 0, 0, 0],\
1310
[0, 2, 0, 1, 2, 1, 1, 0, 0, 0, 0],\
1311
[0, 0, 2, 0, 1, 2, 1, 1, 0, 0, 0],\
1312
[0, 0, 0, 2, 0, 1, 2, 1, 1, 0, 0],\
1313
[0, 0, 0, 0, 2, 0, 1, 2, 1, 1, 0],\
1314
[0, 0, 0, 0, 0, 2, 0, 1, 2, 1, 1]]
1315
V = span(B, F)
1316
return LinearCodeFromVectorSpace(V, d=5)
1317
1318
def ToricCode(P,F):
1319
r"""
1320
Let `P` denote a list of lattice points in
1321
`\ZZ^d` and let `T` denote the set of all
1322
points in `(F^x)^d` (ordered in some fixed way). Put
1323
`n=|T|` and let `k` denote the dimension of the
1324
vector space of functions `V = \mathrm{Span}\{x^e \ |\ e \in P\}`.
1325
The associated toric code `C` is the evaluation code which
1326
is the image of the evaluation map
1327
1328
.. math::
1329
1330
\mathrm{eval_T} : V \rightarrow F^n,
1331
1332
1333
where `x^e` is the multi-index notation
1334
(`x=(x_1,...,x_d)`, `e=(e_1,...,e_d)`, and
1335
`x^e = x_1^{e_1}...x_d^{e_d}`), where
1336
`eval_T (f(x)) = (f(t_1),...,f(t_n))`, and where
1337
`T=\{t_1,...,t_n\}`. This function returns the toric
1338
codes discussed in [J]_.
1339
1340
INPUT:
1341
1342
1343
- ``P`` - all the integer lattice points in a polytope
1344
defining the toric variety.
1345
1346
- ``F`` - a finite field.
1347
1348
1349
OUTPUT: Returns toric code with length n = , dimension k over field
1350
F.
1351
1352
EXAMPLES::
1353
1354
sage: C = codes.ToricCode([[0,0],[1,0],[2,0],[0,1],[1,1]],GF(7))
1355
sage: C
1356
Linear code of length 36, dimension 5 over Finite Field of size 7
1357
sage: C.minimum_distance()
1358
24
1359
sage: C = codes.ToricCode([[-2,-2],[-1,-2],[-1,-1],[-1,0],[0,-1],[0,0],[0,1],[1,-1],[1,0]],GF(5))
1360
sage: C
1361
Linear code of length 16, dimension 9 over Finite Field of size 5
1362
sage: C.minimum_distance()
1363
6
1364
sage: C = codes.ToricCode([ [0,0],[1,1],[1,2],[1,3],[1,4],[2,1],[2,2],[2,3],[3,1],[3,2],[4,1]],GF(8,"a"))
1365
sage: C
1366
Linear code of length 49, dimension 11 over Finite Field in a of size 2^3
1367
1368
This is in fact a [49,11,28] code over GF(8). If you type next
1369
``C.minimum_distance()`` and wait overnight (!), you
1370
should get 28.
1371
1372
AUTHOR:
1373
1374
- David Joyner (07-2006)
1375
1376
REFERENCES:
1377
1378
.. [J] D. Joyner, Toric codes over finite fields, Applicable
1379
Algebra in Engineering, Communication and Computing, 15, (2004), p. 63-79.
1380
"""
1381
from sage.combinat.all import Tuples
1382
mset = [x for x in F if x!=0]
1383
d = len(P[0])
1384
pts = Tuples(mset,d).list()
1385
n = len(pts) # (q-1)^d
1386
k = len(P)
1387
e = P[0]
1388
B = []
1389
for e in P:
1390
tmpvar = [prod([t[i]**e[i] for i in range(d)]) for t in pts]
1391
B.append(tmpvar)
1392
# now B0 *should* be a full rank matrix
1393
MS = MatrixSpace(F,k,n)
1394
return LinearCode(MS(B))
1395
1396
1397
def TrivialCode(F,n):
1398
MS = MatrixSpace(F,1,n)
1399
return LinearCode(MS(0))
1400
1401
1402
def WalshCode(m):
1403
r"""
1404
Returns the binary Walsh code of length `2^m`. The matrix
1405
of codewords correspond to a Hadamard matrix. This is a (constant
1406
rate) binary linear `[2^m,m,2^{m-1}]` code.
1407
1408
EXAMPLES::
1409
1410
sage: C = codes.WalshCode(4); C
1411
Linear code of length 16, dimension 4 over Finite Field of size 2
1412
sage: C = codes.WalshCode(3); C
1413
Linear code of length 8, dimension 3 over Finite Field of size 2
1414
sage: C.spectrum()
1415
[1, 0, 0, 0, 7, 0, 0, 0, 0]
1416
sage: C.minimum_distance()
1417
4
1418
sage: C.minimum_distance(algorithm='gap') # check d=2^(m-1)
1419
4
1420
1421
REFERENCES:
1422
1423
- http://en.wikipedia.org/wiki/Hadamard_matrix
1424
1425
- http://en.wikipedia.org/wiki/Walsh_code
1426
"""
1427
return LinearCode(walsh_matrix(m), d=2**(m-1))
1428
1429