timer_threshold

arrayrange

def Sender(incomingFrame, timerValue, exp_nR, nextInt, buffFrame):
# incomingFrame: dataframe sent from the receiver
# timerValue: value of the timer when last dataframe was sent
# exp_nR: expected nR of upcoming dataframe
# nextInt: next integer to send when sending dataframe
# buffFrame: last sent dataframe from sender to receiver
next_nR = exp_nR
waiting = False
while( not(waiting) ):
# If timer is running and exceeding the timer threshold, resend the packet
if ( not(timerValue == 0) and time.perf_counter() > timerValue + float(timer_threshold)):
outgoingFrame = buffFrame
outgoingFrame[0] = 1
sendFlag = True
waiting = True
timerValue = time.perf_counter()
# If timer is not running, send dataframe containg nextInt
elif (timerValue == 0):
outgoingFrame = [1,exp_nR,nextInt]
sendFlag = True
waiting = True
next_nR = (exp_nR + 1) % 2
timerValue = time.perf_counter()
# If incomingFrame is not corrupt and nR corresponds to the expected nR, then get ready for sending next frame
elif (incomingFrame[0] == 1 and incomingFrame[1] == exp_nR):
outgoingFrame = [0,0,0]
sendFlag = False
waiting = True
timerValue = 0 # Reset timer
# Some delay to keep debugging easy (no flooding of print statements)
#time.sleep(0.000001)
return outgoingFrame, sendFlag, timerValue, next_nR

def Receiver(incomingFrame, nS, buffFrame):
# incomingFrame: Incoming frame from the sender
# nS: Expected nS for incomingFrame
# buffFrame Last sent frame by receiver
# If an uncorrupted and valid frame is received
if (incomingFrame[0] == 1 and incomingFrame[1] == nS):
receiveFlag = True
receivedInt = incomingFrame[2]
nS_next = (nS + 1) % 2
dataFrame = [1,nS_next,receivedInt]
#If the previously sent frame is received again, meaning a corrupted ACK
elif (incomingFrame[0] == 1 and not( incomingFrame[1] == nS) and incomingFrame[2] == buffFrame[2]):
receiveFlag = False
nS_next = nS
receivedInt = incomingFrame[2]
dataFrame = [1,nS,receivedInt]
#If a corrupted or invalid frame is received
else:
receiveFlag = False
nS_next = nS
dataFrame = [0,0,incomingFrame[2]]
receivedInt = -1
return dataFrame, nS_next, receivedInt, receiveFlag
# dataFrame: ACK send to the sender
# nS_next: nS of the next incomingFrame to be received
# receivedInt: Integer received by the receiver.
# receiveFlag: Flag is true if correct frame is received

# Import libraries
import numpy as np
import random
import time
def main():
## Generate random set of integers
inputData = np.random.randint(int(arrayrange), size=int(arraysize))
outputData = []
# Initialize some values (and a simulation timer)
tic = time.perf_counter()
k = 0
nS = 0
dataFrame_RS = [1,0,0]
dataFrame_SR = [0,0,0]
timerValue = 0
next_nR = 0
sendFlag = False
iterations = 0
# Loop the sender / receiver cycle
while(True):
# exit if all integers are sent
if (k == int(arraysize) ):
break
# Send some data
if ( not(sendFlag) ):
[dataFrame_SR, sendFlag, timerValue, next_nR] = Sender(dataFrame_RS, timerValue, next_nR, inputData[k], dataFrame_SR)
# Corrupt data from sender to receiver with a chance p1
if (random.random() < float(p1)):
dataFrame_SR[0] = 0
# If something is sent, run the receiver
if (sendFlag):
[dataFrame_RS, nS, receivedInt, receiveFlag] = Receiver(dataFrame_SR, nS, dataFrame_RS)
sendFlag = False
# If something is (correctly) received, save the value
if (receiveFlag):
outputData.append(receivedInt)
receiveFlag = False
# Corrupt ACK from receiver to sender with a chance p2
if (random.random() < float(p2)):
dataFrame_RS[0] = 0
# Let Sender check for ACK or Timeout (timerValue != 0)
[dataFrame_SR, sendFlag, timerValue, next_nR] = Sender(dataFrame_RS, timerValue, next_nR, inputData[k], dataFrame_SR)
# If ACK received, nothing is sent
if ( not(sendFlag) ):
k = k + 1 # increment k only after received ACK by sender
# Keep track of number of loops used for data transfer
iterations = iterations + 1
# Stop timing of simulation, show report.
toc = time.perf_counter()
# Checking if the output data is the same as the input data. The program continues, but gives the user a notice if it contained an error.
errors = np.count_nonzero(inputData - np.array(outputData))
if (errors > 0):
print("ERRORS IN TRANSMISSION! Input array does not equal output array.")
print("Number of errors: " + str(errors))
return(iterations)

import matplotlib.pyplot as plt
samples = 10
steps = 10
result = np.empty((steps,samples))
p1 = 0
p2 = 0
for j in range(steps):
arraysize = (j+1)*steps
#print("S = " + str(arraysize))
for i in range(samples):
result[j,i] = main()
#print(result)
average = np.average(result, axis=1)
maximum = np.max(result,axis=1) - average
minimum = average - np.min(result,axis=1)
p = np.linspace(10,100,steps)
plt.figure()
plt.errorbar(p, average, yerr=[minimum,maximum], fmt='o', ecolor='red')
plt.title("Number of iterations needed per set size")
plt.xlabel("Number of integers")
plt.ylabel("Number of iterations")
y = p
plt.plot(p,y,"g--")

samples = 10
steps = 20
result = np.empty((steps,samples))
arraysize = 100
p2 = 0
for j in range(steps):
p1 = j / steps
#print("p1 = " + str(p1))
for i in range(samples):
result[j,i] = main()
#print(result)
average = np.average(result, axis=1)
maximum = np.max(result,axis=1) - average
minimum = average - np.min(result,axis=1)
p = np.linspace(0,0.95,steps)
plt.figure()
plt.errorbar(p, average, yerr=[minimum,maximum], fmt='o', ecolor='red')
plt.title("Number of iterations per chance of failure")
plt.xlabel("p1")
plt.ylabel("Nmber of iterations")
y = 100 * (1+(p / (1-p)))
plt.plot(p,y,"g--")

samples = 10
steps = 20
result = np.empty((steps,samples))
arraysize = 100
for j in range(steps):
p1 = float(j) / steps
p2 = p1
#print("p1 = " + str(p1))
for i in range(samples):
result[j,i] = main()
#print(result)
average = np.average(result, axis=1)
maximum = np.max(result,axis=1) - average
minimum = average - np.min(result,axis=1)
p = np.linspace(0,0.95,steps)
plt.figure()
plt.errorbar(p, average, yerr=[minimum,maximum], fmt='o', ecolor='red')
plt.title("Number of iterations per chance of failure")
plt.xlabel("p1=p2")
plt.ylabel("Number of iterations")
y = 100 * (1+(p / (1-p))**2)
plt.plot(p,y,"g--")