Created
August 1, 2013 23:44
-
-
Save sampsyo/6136357 to your computer and use it in GitHub Desktop.
simulate analog storage/transmission errors
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import bitstring | |
import random | |
import json | |
# Randomness. | |
def bernoulli(param): | |
return random.random() <= param | |
def flip(): | |
return bernoulli(0.5) | |
# Gray coding. | |
def bin2gray(bits): | |
out = bitstring.BitArray(len(bits)) | |
out[0] = bits[0] | |
for i in range(1, len(bits)): | |
out[i] = bits[i - 1] ^ bits[i] | |
return out | |
def gray2bin(bits): | |
out = bitstring.BitArray(len(bits)) | |
out[0] = bits[0] | |
for i in range(1, len(bits)): | |
out[i] = out[i - 1] ^ bits[i] | |
return out | |
# Error modeling. This is a traingle-shaped distribution, I think. | |
def cell_error(val, limit, prob): | |
direction = 1 if flip() else -1 | |
while True: | |
if bernoulli(prob): | |
val += direction | |
else: | |
break | |
return max(min(val, limit), 0) | |
# Cellwise, encoded error injection. | |
def error_inject(val, bits, cells, gray, prob): | |
bits_per_cell = bits // cells | |
cell_limit = (2 ** bits_per_cell) - 1 | |
# Encode. | |
valbits = bitstring.BitArray(length=bits, uint=val) | |
if gray: | |
valbits = bin2gray(valbits) | |
# Split value across cells. | |
chunks = [] | |
for cell in range(cells): | |
chunks.append(valbits[cell * bits_per_cell:(cell + 1) * bits_per_cell]) | |
# Inject errors. | |
out_chunks = [] | |
for chunk in chunks: | |
chunk = bitstring.BitArray( | |
length=bits_per_cell, | |
uint=cell_error(chunk.uint, cell_limit, prob), | |
) | |
out_chunks.append(chunk) | |
# Stitch the cell values back together. | |
out_bits = bitstring.BitArray(length=bits) | |
for cell, chunk in enumerate(out_chunks): | |
out_bits[cell * bits_per_cell:(cell + 1) * bits_per_cell] = chunk | |
# Decode. | |
if gray: | |
out_bits = gray2bin(out_bits) | |
return out_bits.uint | |
# Main experiment driver. | |
TRIALS = 100 | |
LEVEL_ERROR_PROB = 0.2 | |
def experiment(bits, cells, gray): | |
for i in range(2 ** bits): | |
total_error = 0 | |
for trial in range(TRIALS): | |
error = i - error_inject(i, bits, cells, gray, | |
LEVEL_ERROR_PROB) | |
total_error += abs(error) | |
yield { | |
'value': i, | |
'error': total_error / TRIALS, | |
'code': 'gray' if gray else 'binary', | |
'bits': bits, | |
'cells': cells, | |
} | |
def main(): | |
results = [] | |
for gray in (False, True): | |
for cells in (1, 2): | |
results += experiment(8, cells, gray) | |
print(json.dumps(results)) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment