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