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

Commit 0ffd780

Browse files
committed
adding ReedMullerCode.py containing support for encoding of Reed Muller Codes
1 parent 1961f94 commit 0ffd780

File tree

1 file changed

+182
-0
lines changed

1 file changed

+182
-0
lines changed

src/sage/coding/ReedMullerCode.py

+182
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
from operator import mul
2+
from sage.matrix.constructor import matrix
3+
from sage.functions.other import binomial
4+
from sage.calculus.var import var
5+
from sage.misc.functional import symbolic_sum
6+
from sage.coding.linear_code import AbstractLinearCode, LinearCodeSyndromeDecoder
7+
from sage.coding.encoder import Encoder
8+
import sage.combinat as subsets
9+
from sage.rings.finite_rings.finite_field_base import FiniteField
10+
11+
#to compute the sum of n chose i where i ranges from 0 to k
12+
def binomialSum(n,k):
13+
s=1
14+
nCi=1
15+
for i in range(k):
16+
nCi=((n-i)*nCi)/(i+1)
17+
s=nCi+s
18+
return s
19+
20+
#to use the evaluation of polynomial at the points to obtain the polynomial
21+
def multivariatePolynomialInterpolation(evaluation, numberOfVariable, order, q, finiteField, _R):
22+
if numberOfVariable==0 or order==0:
23+
return evaluation[0]
24+
xcordinate=finiteField.list()
25+
nq=q**(numberOfVariable-1)
26+
d=min(order+1,q)
27+
evaluation2=[]
28+
uniPolyRing=PolynomialRing(finiteField,'x')
29+
for k in range(nq):
30+
points=[(xcordinate[i], evaluation[k+i*nq]) for i in range(q)]
31+
polyVector=uniPolyRing.lagrange_polynomial(points).coefficients(sparse=False)
32+
if len(polyVector)<d:
33+
#adding zeros to represet a (d-1) degree polynomial
34+
polyVector=polyVector+[0 for i in range(d-len(polyVector))]
35+
evaluation2.append(polyVector)
36+
poly=0
37+
z=1
38+
x=_R.gen(numberOfVariable-1)
39+
for k in range(d):#computing the polynomial
40+
poly=poly+z*multivariatePolynomialInterpolation([evaluation2[i][k] for i in range(nq)], numberOfVariable-1, order-k, q, finiteField, _R)
41+
z=z*x
42+
return poly
43+
44+
def ReedMullerCode(finiteField, order, numberOfVariable):
45+
if (isinstance(finiteField,FiniteField)):
46+
baseField=finiteField
47+
q=baseField.cardinality()
48+
elif (isinstance(finiteField, Integer)):
49+
baseField=GF(finiteField, 'x')
50+
q=finiteField
51+
if q == 2:
52+
return BinaryReedMullerCode(order, numberOfVariable)
53+
else:
54+
return QAryReedMullerCode(baseField, order, numberOfVariable)
55+
56+
class QAryReedMullerCode(AbstractLinearCode):
57+
_registered_encoders={}
58+
_registered_decoders={}
59+
60+
def __init__(self, finiteField, order, numberOfVariable):
61+
#to handle the case when the base field is directly given and input sanitization
62+
if (isinstance(finiteField,FiniteField)):
63+
baseField=finiteField
64+
q=baseField.cardinality()
65+
elif (isinstance(finiteField, Integer)):
66+
baseField=GF(finiteField, 'x')
67+
q=finiteField
68+
else:
69+
raise ValueError("Incorrect data-type of input: You must either give the size of the finite field or the finite field itself")
70+
if not(isinstance(order,Integer)):
71+
raise ValueError("Incorrect data-type of input: The order of the code must be an integer")
72+
if not(isinstance(numberOfVariable, Integer)):
73+
raise ValueError("Incorrect data-type of input: The number of variables must be an integer")
74+
if (order>=q):
75+
raise ValueError("The order must be less than %s" % q)
76+
77+
super(QAryReedMullerCode, self).__init__(baseField,q**numberOfVariable,"ReedMullerVectorEncoder","Syndrome")
78+
self.order=order
79+
self.numberOfVariable=numberOfVariable
80+
self.q=q
81+
self._dimension=binomial(numberOfVariable+order, order)
82+
83+
def _repr_(self):
84+
return "%s-ary Reed Muller Code of order %s and number of variables %s" % (self.q, self.order, self.numberOfVariable)
85+
86+
def _latex_(self):
87+
return "%s\textnormal{-ary Reed Muller Code of order} %s \textnormal{and number of variables} %s" % (self.q, self.order, self.numberOfVariable)
88+
89+
def __eq__(self,other):
90+
return (isinstance(other, QAryReedMullerCode)) and self.q==other.q and self.order==other.order and self.numberOfVariable==other.numberOfVariable
91+
92+
class BinaryReedMullerCode(AbstractLinearCode):
93+
_registered_encoders={}
94+
_registered_decoders={}
95+
96+
def __init__(self, order, numberOfVariable):
97+
#input sanitization
98+
if not(isinstance(order,Integer)):
99+
raise ValueError("Incorrect data-type of input: The order of the code must be an integer")
100+
if not(isinstance(numberOfVariable, Integer)):
101+
raise ValueError("Incorrect data-type of input: The number of variables must be an integer")
102+
if (numberOfVariable<order):
103+
raise ValueError("The order must be less than %s" % numberOfVariable)
104+
105+
super(BinaryReedMullerCode, self).__init__(GF(2), 2**numberOfVariable,"ReedMullerVectorEncoder","Syndrome")
106+
self.order=order
107+
self.numberOfVariable=numberOfVariable
108+
self.q=2
109+
self._dimension=binomialSum(numberOfVariable,order)
110+
111+
def _repr_(self):
112+
return "Binary Reed Muller Code of order %s and number of variables %s" % (self.order, self.numberOfVariable)
113+
114+
def _latex_(self):
115+
return "\textnormal{Binary Reed Muller Code of order} %s \textnormal{and number of variables} %s" % (self.q, self.order, self.numberOfVariable)
116+
117+
def __eq__(self,other):
118+
return (isinstance(other, BinaryReedMullerCode)) and self.order==other.order and self.numberOfVariable==other.numberOfVariable
119+
120+
class ReedMullerVectorEncoder(Encoder):
121+
def __init__(self, code):
122+
super(ReedMullerVectorEncoder, self).__init__(code)
123+
124+
def _repr_(self):
125+
return "Evaluation polynomial-style encoder for %s" % self.code()
126+
127+
def _latex_(self):
128+
return "\textnormal{Evaluation polynomial-style encoder for }%s" % self.code()._latex_()
129+
130+
def __eq__(self,other):
131+
return (isinstance(other, ReedMullerVectorEncoder)) and self.code==other.code
132+
133+
def generator_matrix(self):
134+
C=self.code()
135+
baseField=C.base_field()
136+
order=C.order
137+
numberOfVariable=C.numberOfVariable
138+
q=C.q
139+
baseFieldTuple=Tuples(baseField.list(),numberOfVariable)
140+
exponents=Subsets(range(numberOfVariable)*(q-1), submultiset=True)[0:C.dimension()]
141+
return Matrix(baseField, [[reduce(mul, [x[i] for i in exponent],1) for x in baseFieldTuple] for exponent in exponents])
142+
143+
class ReedMullerPolynomialEncoder(Encoder):
144+
def __init__(self, code):
145+
super(ReedMullerPolynomialEncoder, self).__init__(code)
146+
self._R=PolynomialRing(self.code().base_field(),self.code().numberOfVariable,"x")
147+
148+
def _repr_(self):
149+
return "Evaluation polynomial-style encoder for %s" % self.code()
150+
151+
def _latex_(self):
152+
return "\textnormal{Evaluation polynomial-style encoder for }%s" % self.code()._latex_()
153+
154+
def __eq__(self,other):
155+
return (isinstance(other, ReedMullerPolynomialEncoder)) and self.code==other.code
156+
157+
def encode(self, p):
158+
M = self.message_space()
159+
if p not in M:
160+
raise ValueError("The value to encode must be in %s" % M)
161+
C=self.code()
162+
if p.degree() > C.order:
163+
raise ValueError("The polynomial to encode must have degree at most %s" % C.order)
164+
baseFieldTuple = Tuples(C.base_field().list(), C.numberOfVariable)
165+
return vector(C.base_ring(), [p(x) for x in baseFieldTuple])
166+
167+
def unencode_nocheck(self, c):
168+
return multivariatePolynomialInterpolation(c, self.code().numberOfVariable, self.code().order, self.code().q, self.code().base_field(), self._R)
169+
170+
171+
def message_space(self):
172+
return self._R
173+
174+
QAryReedMullerCode._registered_encoders["ReedMullerVectorEncoder"] = ReedMullerVectorEncoder
175+
QAryReedMullerCode._registered_encoders["ReedMullerPolynomialEncoder"] = ReedMullerPolynomialEncoder
176+
177+
QAryReedMullerCode._registered_decoders["Syndrome"] = LinearCodeSyndromeDecoder
178+
179+
BinaryReedMullerCode._registered_encoders["ReedMullerVectorEncoder"] = ReedMullerVectorEncoder
180+
BinaryReedMullerCode._registered_encoders["ReedMullerPolynomialEncoder"] = ReedMullerPolynomialEncoder
181+
182+
BinaryReedMullerCode._registered_decoders["Syndrome"] = LinearCodeSyndromeDecoder

0 commit comments

Comments
 (0)