Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
I
ISC_122 - Travail Pratique 001 - Code de Reed-Solomon
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
florian.burgener
ISC_122 - Travail Pratique 001 - Code de Reed-Solomon
Commits
393cc838
Commit
393cc838
authored
3 years ago
by
florian.burgener
Browse files
Options
Downloads
Patches
Plain Diff
Add comments
parent
be40b6a3
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
polynomial.py
+117
-40
117 additions, 40 deletions
polynomial.py
with
117 additions
and
40 deletions
polynomial.py
+
117
−
40
View file @
393cc838
import
math
from
numbers
import
Number
import
itertools
import
json
from
typing
import
Tuple
def
unicode_superscripts
(
value
):
def
unicode_superscripts
(
number
):
"""
Convert a number into a string of unicode characters superscripts.
Args:
number (int): The number to convert.
Returns:
str: The unicode superscripts string.
"""
exponent_dict
=
{
"
0
"
:
"
⁰
"
,
"
1
"
:
"
¹
"
,
"
2
"
:
"
²
"
,
"
3
"
:
"
³
"
,
"
4
"
:
"
⁴
"
,
"
5
"
:
"
⁵
"
,
"
6
"
:
"
⁶
"
,
"
7
"
:
"
⁷
"
,
"
8
"
:
"
⁸
"
,
"
9
"
:
"
⁹
"
}
return
(
"
⁻
"
if
value
<
0
else
""
)
+
""
.
join
(
exponent_dict
[
x
]
for
x
in
str
(
abs
(
value
)))
return
(
"
⁻
"
if
number
<
0
else
""
)
+
""
.
join
(
exponent_dict
[
x
]
for
x
in
str
(
abs
(
number
)))
class
Polynomial
:
"""
Class for manipulating polynomials.
"""
def
__init__
(
self
,
value
=
()):
"""
Creates an instance of Polynomial with a polynomial defined in a tuple.
Args:
value (tuple, optional): Polynomial defined in a tuple. Defaults to ().
Raises:
TypeError: The type of the parameter
"
value
"
is not a tuple.
"""
if
not
isinstance
(
value
,
tuple
):
raise
TypeError
(
'
The
"
value
"
parameter is not of type tuple.
'
)
self
.
value
=
value
def
pass_x_throughout
(
self
,
x
):
"""
Evaluate the polynomial by passing x
Args:
x (int): The x to evaluate.
Returns:
int: The result of the evaluation.
"""
a
=
list
(
self
.
value
)
sum
=
(
a
[
len
(
a
)
-
1
]
*
x
)
+
a
[
len
(
a
)
-
2
]
for
i
in
reversed
(
range
(
len
(
a
)
-
2
)):
sum
=
sum
*
x
+
a
[
i
]
return
sum
def
__add__
(
self
,
other
):
"""
Add two polynomials.
Args:
other (Polynomial): The second polynomial to be added.
Returns:
Polynomial: The result of the addition.
"""
a
=
list
(
self
.
value
)
b
=
list
(
other
.
value
)
...
...
@@ -45,35 +78,51 @@ class Polynomial:
return
Polynomial
(
tuple
(
c
))
def
__mul__
(
self
,
other
):
"""
Multiply two polynomials.
Args:
other (Polynomial): The second polynomial to be multiplied.
Returns:
Polynomial: The result of the multiplication.
"""
a
=
list
(
self
.
value
)
b
=
list
(
other
.
value
)
a_count
=
len
(
a
)
b_count
=
len
(
b
)
size
=
(
a_count
-
1
)
+
(
b_count
-
1
)
+
1
size
=
(
len
(
a
)
-
1
)
+
(
len
(
b
)
-
1
)
+
1
c
=
[
0
]
*
size
for
i
in
range
(
a_count
):
for
j
in
range
(
b_count
):
for
i
in
range
(
len
(
a
)
):
for
j
in
range
(
len
(
b
)
):
c
[
i
+
j
]
+=
a
[
i
]
*
b
[
j
]
return
Polynomial
(
tuple
(
c
))
def
__mod__
(
self
,
other
):
"""
Apply a modulo on the polynomial.
Args:
other (int): The modulo to apply.
Returns:
Polynomial: The result of the modolu operation.
"""
a
=
list
(
self
.
value
)
result
=
[
0
]
*
len
(
a
)
for
i
in
range
(
len
(
a
)):
result
[
i
]
=
a
[
i
]
%
other
for
i
in
reversed
(
range
(
len
(
result
))):
if
result
[
i
]
==
0
:
del
result
[
i
]
else
:
break
return
Polynomial
(
tuple
(
result
))
def
__str__
(
self
):
"""
Convert a polynomial into a string.
Returns:
str: The polynomial converts to a string.
"""
str_value
=
""
for
i
,
x
in
enumerate
(
reversed
(
self
.
value
)):
...
...
@@ -92,67 +141,96 @@ class Polynomial:
return
str_value
def
compute_bachet_bezout
(
a
,
b
):
def
get_bezout_coefficients
(
a
,
b
):
"""
Find the Bézout coefficients of a and b.
Args:
a (int): The number a
b (int): The number b.
Returns:
tuple: Bézout coefficients.
"""
r
=
[
a
,
b
]
x
=
[
1
,
0
]
y
=
[
0
,
1
]
q
=
[
0
,
0
]
# Computing
i
=
1
while
r
[
i
]
>
0
:
i
+=
1
r
.
append
(
r
[
i
-
2
]
%
r
[
i
-
1
])
q
.
append
(
int
(
r
[
i
-
2
]
/
r
[
i
-
1
]))
if
r
[
i
]
>
0
:
x
.
append
(
x
[
i
-
2
]
-
q
[
i
]
*
x
[
i
-
1
])
y
.
append
(
y
[
i
-
2
]
-
q
[
i
]
*
y
[
i
-
1
])
return
x
[
-
1
],
y
[
-
1
]
def
modular_inverse
(
a
,
n
):
coefficients
=
compute_bachet_bezout
(
a
,
n
)
"""
Compute the modular inverse of a number a modolu n.
Args:
a (int): The number to reverse.
n (int): The modolu.
Returns:
int: The reversed number.
"""
coefficients
=
get_bezout_coefficients
(
a
,
n
)
if
a
*
coefficients
[
0
]
%
n
==
1
:
return
coefficients
[
0
]
%
n
return
None
def
compute_lagrange_polynomial
(
points
,
prime_number
):
nb_points
=
len
(
points
)
lagrange
=
Polynomial
((
0
,))
"""
Compute the Lagrange polynomial passing through all points.
# Create a polynomial for each points
for
i
in
range
(
nb_points
):
poly_li
=
Polynomial
((
1
,))
divider
=
1
Args:
points (list): List of points.
prime_number (int): The prime number.
# Compute the lagrange polynomial
for
k
in
range
(
nb_points
):
if
k
!=
i
:
dividend
=
Polynomial
((
-
points
[
k
][
0
],
1
))
# x - value
Returns:
Polynomial: The Lagrange polynomial passing through all points.
"""
# Polynomial L(x)
L_polynomial
=
Polynomial
((
0
,))
poly_li
*=
dividend
divider
*=
points
[
i
][
0
]
-
points
[
k
][
0
]
# Create the Li(x) polynomial.
for
i
,
(
xi
,
yi
)
in
enumerate
(
points
):
Li_polynomial
=
Polynomial
((
1
,))
divider
=
modular_inverse
(
divider
,
prime_number
)
point_yi
=
points
[
i
][
1
]
poly_li
=
poly_li
*
Polynomial
((
divider
,))
*
Polynomial
((
point_yi
,))
# For each point except the point at index i.
for
j
,
(
xj
,
_
)
in
enumerate
(
points
):
if
j
!=
i
:
Li_polynomial
*=
Polynomial
((
-
xj
,
1
))
Li_polynomial
*=
Polynomial
((
modular_inverse
(
xi
-
xj
,
prime_number
),))
Li_polynomial
*=
Polynomial
((
yi
,))
L_polynomial
+=
Li_polynomial
return
L_polynomial
%
prime_number
lagrange
+=
poly_li
lagrange
%=
prime_number
return
lagrange
def
reed_solomon
(
points
,
data_length
,
last_error_index
,
prime_number
):
"""
Applies the Reed-Solomon method to correct message errors.
Args:
points (list): List of points.
data_length (int): Data length.
last_error_index (int): The index of the last error.
prime_number (int): The prime number.
def
reed_solomon
(
points
,
data_length
,
last_error_index
,
prime_number
):
Returns:
str: The corrected message.
"""
combination_length
=
data_length
-
len
(
points
[:
last_error_index
])
# Parse each combination of points possible (exclude the correct points)
for
x
in
itertools
.
combinations
(
points
[:
last_error_index
+
1
],
combination_length
):
nb_valid_points
=
0
# Create a sublist of points with all corrects points and the current combination of points
sub_points
=
list
(
x
)
+
points
[
last_error_index
+
1
:]
sub_points
=
list
(
x
)
+
points
[
last_error_index
+
1
:]
# Create the lagrange polynomial with the sublist of points
lagrange
=
compute_lagrange_polynomial
(
sub_points
,
prime_number
)
...
...
@@ -169,7 +247,7 @@ def reed_solomon(points, data_length, last_error_index, prime_number):
# Verify if we have enough valid points, so it must be equal or higher than m + n points
if
nb_valid_points
>=
data_length
+
(
len
(
points
)
-
data_length
)
//
2
:
# // = euclid division
# Decode the message
output
=
''
output
=
""
for
i
in
range
(
data_length
):
output
+=
chr
(
lagrange
.
pass_x_throughout
(
i
)
%
prime_number
)
...
...
@@ -181,7 +259,6 @@ def reed_solomon(points, data_length, last_error_index, prime_number):
def
main
():
message
=
{
"
data_length
"
:
25
,
"
last_error_index
"
:
23
,
"
prime_number
"
:
401
,
"
points
"
:
[
67
,
101
,
38
,
109
,
101
,
115
,
133
,
118
,
103
,
128
,
62
,
118
,
97
,
156
,
116
,
77
,
49
,
56
,
86
,
112
,
171
,
105
,
176
,
116
,
115
,
183
,
30
,
315
,
368
,
29
,
352
,
54
,
333
,
198
,
139
,
234
,
321
,
92
,
5
,
272
,
396
,
265
,
397
,
386
,
229
,
153
,
276
]}
points
=
[(
x
,
y
)
for
x
,
y
in
enumerate
(
message
[
"
points
"
])]
print
(
points
)
corrected_data
=
reed_solomon
(
points
,
message
[
"
data_length
"
],
message
[
"
last_error_index
"
],
message
[
"
prime_number
"
])
print
(
corrected_data
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment