TheAlgorithms-Python
292 строки · 9.1 Кб
1# Author: João Gustavo A. Amorim & Gabriel Kunz
2# Author email: joaogustavoamorim@gmail.com and gabriel-kunz@uergs.edu.br
3# Coding date: apr 2019
4# Black: True
5
6"""
7* This code implement the Hamming code:
8https://en.wikipedia.org/wiki/Hamming_code - In telecommunication,
9Hamming codes are a family of linear error-correcting codes. Hamming
10codes can detect up to two-bit errors or correct one-bit errors
11without detection of uncorrected errors. By contrast, the simple
12parity code cannot correct errors, and can detect only an odd number
13of bits in error. Hamming codes are perfect codes, that is, they
14achieve the highest possible rate for codes with their block length
15and minimum distance of three.
16
17* the implemented code consists of:
18* a function responsible for encoding the message (emitterConverter)
19* return the encoded message
20* a function responsible for decoding the message (receptorConverter)
21* return the decoded message and a ack of data integrity
22
23* how to use:
24to be used you must declare how many parity bits (sizePari)
25you want to include in the message.
26it is desired (for test purposes) to select a bit to be set
27as an error. This serves to check whether the code is working correctly.
28Lastly, the variable of the message/word that must be desired to be
29encoded (text).
30
31* how this work:
32declaration of variables (sizePari, be, text)
33
34converts the message/word (text) to binary using the
35text_to_bits function
36encodes the message using the rules of hamming encoding
37decodes the message using the rules of hamming encoding
38print the original message, the encoded message and the
39decoded message
40
41forces an error in the coded text variable
42decodes the message that was forced the error
43print the original message, the encoded message, the bit changed
44message and the decoded message
45"""
46
47# Imports
48import numpy as np49
50
51# Functions of binary conversion--------------------------------------
52def text_to_bits(text, encoding="utf-8", errors="surrogatepass"):53"""54>>> text_to_bits("msg")
55'011011010111001101100111'
56"""
57bits = bin(int.from_bytes(text.encode(encoding, errors), "big"))[2:]58return bits.zfill(8 * ((len(bits) + 7) // 8))59
60
61def text_from_bits(bits, encoding="utf-8", errors="surrogatepass"):62"""63>>> text_from_bits('011011010111001101100111')
64'msg'
65"""
66n = int(bits, 2)67return n.to_bytes((n.bit_length() + 7) // 8, "big").decode(encoding, errors) or "\0"68
69
70# Functions of hamming code-------------------------------------------
71def emitter_converter(size_par, data):72"""73:param size_par: how many parity bits the message must have
74:param data: information bits
75:return: message to be transmitted by unreliable medium
76- bits of information merged with parity bits
77
78>>> emitter_converter(4, "101010111111")
79['1', '1', '1', '1', '0', '1', '0', '0', '1', '0', '1', '1', '1', '1', '1', '1']
80>>> emitter_converter(5, "101010111111")
81Traceback (most recent call last):
82...
83ValueError: size of parity don't match with size of data
84"""
85if size_par + len(data) <= 2**size_par - (len(data) - 1):86raise ValueError("size of parity don't match with size of data")87
88data_out = []89parity = []90bin_pos = [bin(x)[2:] for x in range(1, size_par + len(data) + 1)]91
92# sorted information data for the size of the output data93data_ord = []94# data position template + parity95data_out_gab = []96# parity bit counter97qtd_bp = 098# counter position of data bits99cont_data = 0100
101for x in range(1, size_par + len(data) + 1):102# Performs a template of bit positions - who should be given,103# and who should be parity104if qtd_bp < size_par:105if (np.log(x) / np.log(2)).is_integer():106data_out_gab.append("P")107qtd_bp = qtd_bp + 1108else:109data_out_gab.append("D")110else:111data_out_gab.append("D")112
113# Sorts the data to the new output size114if data_out_gab[-1] == "D":115data_ord.append(data[cont_data])116cont_data += 1117else:118data_ord.append(None)119
120# Calculates parity121qtd_bp = 0 # parity bit counter122for bp in range(1, size_par + 1):123# Bit counter one for a given parity124cont_bo = 0125# counter to control the loop reading126for cont_loop, x in enumerate(data_ord):127if x is not None:128try:129aux = (bin_pos[cont_loop])[-1 * (bp)]130except IndexError:131aux = "0"132if aux == "1" and x == "1":133cont_bo += 1134parity.append(cont_bo % 2)135
136qtd_bp += 1137
138# Mount the message139cont_bp = 0 # parity bit counter140for x in range(size_par + len(data)):141if data_ord[x] is None:142data_out.append(str(parity[cont_bp]))143cont_bp += 1144else:145data_out.append(data_ord[x])146
147return data_out148
149
150def receptor_converter(size_par, data):151"""152>>> receptor_converter(4, "1111010010111111")
153(['1', '0', '1', '0', '1', '0', '1', '1', '1', '1', '1', '1'], True)
154"""
155# data position template + parity156data_out_gab = []157# Parity bit counter158qtd_bp = 0159# Counter p data bit reading160cont_data = 0161# list of parity received162parity_received = []163data_output = []164
165for i, item in enumerate(data, 1):166# Performs a template of bit positions - who should be given,167# and who should be parity168if qtd_bp < size_par and (np.log(i) / np.log(2)).is_integer():169data_out_gab.append("P")170qtd_bp = qtd_bp + 1171else:172data_out_gab.append("D")173
174# Sorts the data to the new output size175if data_out_gab[-1] == "D":176data_output.append(item)177else:178parity_received.append(item)179
180# -----------calculates the parity with the data181data_out = []182parity = []183bin_pos = [bin(x)[2:] for x in range(1, size_par + len(data_output) + 1)]184
185# sorted information data for the size of the output data186data_ord = []187# Data position feedback + parity188data_out_gab = []189# Parity bit counter190qtd_bp = 0191# Counter p data bit reading192cont_data = 0193
194for x in range(1, size_par + len(data_output) + 1):195# Performs a template position of bits - who should be given,196# and who should be parity197if qtd_bp < size_par and (np.log(x) / np.log(2)).is_integer():198data_out_gab.append("P")199qtd_bp = qtd_bp + 1200else:201data_out_gab.append("D")202
203# Sorts the data to the new output size204if data_out_gab[-1] == "D":205data_ord.append(data_output[cont_data])206cont_data += 1207else:208data_ord.append(None)209
210# Calculates parity211qtd_bp = 0 # parity bit counter212for bp in range(1, size_par + 1):213# Bit counter one for a certain parity214cont_bo = 0215for cont_loop, x in enumerate(data_ord):216if x is not None:217try:218aux = (bin_pos[cont_loop])[-1 * (bp)]219except IndexError:220aux = "0"221if aux == "1" and x == "1":222cont_bo += 1223parity.append(str(cont_bo % 2))224
225qtd_bp += 1226
227# Mount the message228cont_bp = 0 # Parity bit counter229for x in range(size_par + len(data_output)):230if data_ord[x] is None:231data_out.append(str(parity[cont_bp]))232cont_bp += 1233else:234data_out.append(data_ord[x])235
236ack = parity_received == parity237return data_output, ack238
239
240# ---------------------------------------------------------------------
241"""
242# Example how to use
243
244# number of parity bits
245sizePari = 4
246
247# location of the bit that will be forced an error
248be = 2
249
250# Message/word to be encoded and decoded with hamming
251# text = input("Enter the word to be read: ")
252text = "Message01"
253
254# Convert the message to binary
255binaryText = text_to_bits(text)
256
257# Prints the binary of the string
258print("Text input in binary is '" + binaryText + "'")
259
260# total transmitted bits
261totalBits = len(binaryText) + sizePari
262print("Size of data is " + str(totalBits))
263
264print("\n --Message exchange--")
265print("Data to send ------------> " + binaryText)
266dataOut = emitterConverter(sizePari, binaryText)
267print("Data converted ----------> " + "".join(dataOut))
268dataReceiv, ack = receptorConverter(sizePari, dataOut)
269print(
270"Data receive ------------> "
271+ "".join(dataReceiv)
272+ "\t\t -- Data integrity: "
273+ str(ack)
274)
275
276
277print("\n --Force error--")
278print("Data to send ------------> " + binaryText)
279dataOut = emitterConverter(sizePari, binaryText)
280print("Data converted ----------> " + "".join(dataOut))
281
282# forces error
283dataOut[-be] = "1" * (dataOut[-be] == "0") + "0" * (dataOut[-be] == "1")
284print("Data after transmission -> " + "".join(dataOut))
285dataReceiv, ack = receptorConverter(sizePari, dataOut)
286print(
287"Data receive ------------> "
288+ "".join(dataReceiv)
289+ "\t\t -- Data integrity: "
290+ str(ack)
291)
292"""
293