Skip to content

Instantly share code, notes, and snippets.

@sampsyo
Created August 1, 2013 23:44
Show Gist options
  • Save sampsyo/6136357 to your computer and use it in GitHub Desktop.
Save sampsyo/6136357 to your computer and use it in GitHub Desktop.
simulate analog storage/transmission errors
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